Skip to content

Redis哨兵(sentinel)

Alt text 吹哨人巡査监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库,继续对外服务。

1. 哨兵的作用

  1. 不存放数据,监控redis运行状态是否正常,包括master和slave
  2. 当master down机,能自动将slave切换成新master
  3. 客户端通过连接哨兵来获得当前Redis服务的主节点地址
  4. 哨兵可以将故障转移的结果发送给客户端 Alt text

2. 集群设计

角色哨兵
机器mysql01mysql02mysql01,mysql02

建议哨兵搭建至少2个,避免单个哨兵网络抖动等原因主观误判导致主从切换反而出现问题。

3. Redis哨兵搭建

3.1 前期准备

  1. 复制一份sentinel.conf到conf中
sh
cp redis-7.2.4/sentinel.conf redis-7.2.4/conf/sentinel.conf

3.2 配置哨兵

sh
vim redis-7.2.4/conf/sentinel.conf
## 配置如下内容
# bind 0.0.0.0
daemonize yes
protected-mode no
port 26379
logfile "/opt/module/redis-7.2.4/logs/redis-sentinel.log"
pidfile /opt/module/redis-7.2.4/logs/redis-sentinel.pid
dir /opt/module/redis-7.2.4
sentinel monitor mymaster 192.168.154.141 6379 2
sentinel auth-user mymaster sentinel-user
sentinel auth-pass mymaster 123456

重要参数说明:

  1. 设置要监控的master服务器,格式为sentinel monitor <master-name> <ip> <redis-port> <quorum>, 具体配置中mymaster是主节点的名字,192.168.154.141为初始化master的ip,6379为端口,2表示确认客观下线的最少的哨兵数量。
  2. 设置连接master的认证密码,格式为sentinel auth-pass <master-name> <password>。表示为连接master服务器的用户密码。
  3. 设置连接master的认证用户,格式为sentinel auth-pass <master-name> <user>。表示为连接master服务器的用户。

4. 创建监控用户

在master节点上创建用户

sh
acl setuser sentinel-user on >123456 +client allchannels +subscribe +publish +ping +info +multi +slaveof +config +client +exec
acl save

5. 启动哨兵

启动哨兵之前确认主从Redis都已经启动完毕。

sh
## 启动方式1
jack@mysql01:/opt/module/redis-7.2.4$ ./src/redis-sentinel conf/sentinel.conf 
## 启动方式2
jack@mysql01:/opt/module/redis-7.2.4$ ./src/redis-server conf/sentinel.conf --sentinel

6. 查看哨兵集群情况

登录其中一台哨兵redis上:

sh
./src/redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_tilt_since_seconds:-1
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.154.141:6379,slaves=1,sentinels=2

sentinels等于2,当前的slave从节点是1个。
还可以通过查看日志的方式:

sh
jack@mysql02:/opt/module/redis-7.2.4$ cat logs/redis-sentinel.log
354533:X 28 Apr 2025 17:36:11.446 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
354533:X 28 Apr 2025 17:36:11.446 * Redis version=7.2.4, bits=64, commit=00000000, modified=0, pid=354533, just started
354533:X 28 Apr 2025 17:36:11.446 * Configuration loaded
354533:X 28 Apr 2025 17:36:11.447 * Increased maximum number of open files to 10032 (it was originally set to 1024).
354533:X 28 Apr 2025 17:36:11.447 * monotonic clock: POSIX clock_gettime
354533:X 28 Apr 2025 17:36:11.447 * Running mode=sentinel, port=26379.
354533:X 28 Apr 2025 17:36:11.486 . Rewritten config file (/opt/module/redis-7.2.4/conf/sentinel.conf) successfully
354533:X 28 Apr 2025 17:36:11.486 * Sentinel new configuration saved on disk
354533:X 28 Apr 2025 17:36:11.486 * Sentinel ID is 5c07c0bf1fec18d0197470c0ce7b5c6f4feee183
354533:X 28 Apr 2025 17:36:11.486 # +monitor master mymaster 192.168.154.141 6379 quorum 2
354533:X 28 Apr 2025 17:36:11.513 * +slave slave 192.168.154.142:6379 192.168.154.142 6379 @ mymaster 192.168.154.141 6379
354533:X 28 Apr 2025 17:36:11.553 . Rewritten config file (/opt/module/redis-7.2.4/conf/sentinel.conf) successfully
354533:X 28 Apr 2025 17:36:11.553 * Sentinel new configuration saved on disk
354533:X 29 Apr 2025 09:13:49.330 - Accepted 192.168.154.141:34410
354533:X 29 Apr 2025 09:13:51.181 * +sentinel sentinel 5d7237f9e8234047c96fafa3b97be11170f89331 192.168.154.141 26379 @ mymaster 192.168.154.141 6379
354533:X 29 Apr 2025 09:13:51.223 . Rewritten config file (/opt/module/redis-7.2.4/conf/sentinel.conf) successfully
354533:X 29 Apr 2025 09:13:51.223 * Sentinel new configuration saved on disk
354533:X 29 Apr 2025 09:15:43.839 - Accepted 127.0.0.1:56558
354533:X 29 Apr 2025 09:21:52.677 - Client closed connection id=4 addr=127.0.0.1:56558 laddr=127.0.0.1:26379 fd=13 name= age=369 idle=363 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=0 qbuf-free=20474 argv-mem=0 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 tot-mem=22400 events=r cmd=info user=default redir=-1 resp=2 lib-name= lib-ver=

7. 测试故障转移

  1. 手动关闭master,模拟主节点宕机:
sh
jack@mysql01:/opt/module/redis-7.2.4$ ./src/redis-cli -p 6379
127.0.0.1:6379> shutdown
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth default 123456
OK
127.0.0.1:6379> shutdown
not connected>

等待一会连接从节点:

sh
jack@mysql02:/opt/module/redis-7.2.4$ ./src/redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:a516be5141ec9ec42163af8a6b57bd08cae69ee3
master_replid2:ec0ac4fca26478b72cf29897f3aef8e7955501bd
master_repl_offset:283323
second_repl_offset:283324
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:283323

查看sentinel的日志:
Alt text 可以看到从节点192.168.154.142成功变成master节点。此时再启动主节点的redis:

sh
jack@mysql01:/opt/module/redis-7.2.4$ ./src/redis-server conf/redis.conf
jack@mysql01:/opt/module/redis-7.2.4$ src/redis-cli -p 6379
127.0.0.1:6379> auth default 123456
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.154.142
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_read_repl_offset:283407
slave_repl_offset:283407
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:a516be5141ec9ec42163af8a6b57bd08cae69ee3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:283407
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:283324
repl_backlog_histlen:84

可以发现192.168.154.141不再是主节点,192.168.154.142变成了它的主节点。

8. 哨兵机制原理

8.1 哨兵启动

  1. 哨兵启动后会拿着用户密码信息连接master节点,通过发布/订阅主库的__sentinel__:hello频道, 实现哨兵之间发现和通信。发布自己的节点消息,订阅该频道其他哨兵消息。消息内容为下图,还通过通过info命令得到从节点的信息,包括从节点列表、复制状态等
    Alt text
  2. 哨兵之间建立连接后,会对master节点进行监控,周期性(默认每1秒)地向master发送ping命令,检测master和从节点状态;周期性地每10秒会向主节点和从节点发送INFO命令,每2秒会通过主节点的__sentinel__:hello 频道发布自身信息,同时也会订阅该频道,用于发现其他Sentinel节点。

PING命令和INFO命令周期设置

ini
# 修改向所有节点发送 PING 命令的周期,单位为毫秒
sentinel announce-period 5000
# 修改向主从节点发送 INFO 命令的周期,单位为秒
sentinel resolve-hostnames-period 20

8.2 哨兵判断master下线

  1. 当master失效后,单个sentinel检测到的关于master的状态,就是从sentinel的角度来看如果发送了PING心跳后,一定时间内没有收到合法的回复,就认为是SDown主观下线(Subjectively Down)。
  2. 当Sentinel节点将主节点标记为主观下线(SDOWN)后,就立即向其他Sentinel节点发送询问,确认主节点是否真的下线。如果多个哨兵达成一致意见(前面配置quorum数量)才能认为一个master客观上已经宕掉,此时就认为是ODown客观下线(Objectively Down)。

8.3 哨兵进行故障转移

  1. 当主节点被判断客观下线以后,各个哨兵节点会进行协商选举(Raft算法)出一个Sentinel leader(哨兵领导者)节点并由该领导者节点进行failover(故障迁移)。
  2. 哨兵领导者会进行按照如下master规则从slave节点列表中选出master。 Alt text
  3. Sentinel leader会对选举出的新master进行slaveof no one命令,将其提升为master。
  4. Sentinel leader向对其他slave节点发送命令,让剩余的slave成为新master主节点的slave。
  5. 如果后面老master重新上线后,它会成为新master的从节点,从而恢复正常工作。

上述failover(故障迁移)操作均由sentinel本身自动完成,无需人工干预。

9. 哨兵的使用建议

  1. 哨兵节点的数量应为多个。哨兵本身应该是集群,保证高可用。
  2. 哨兵节点的个数应该为奇数。
  3. 各个哨兵的配置保持一致,包括服务器硬件设备。以免影响公平的投票机制。
  4. 如果哨兵节点部署在Docker等容器上,一定要保证端口的正确映射。
  5. 哨兵集群+主从复制方案并不能保证数据的零丢失。由于只有一台master ,当master宕机之后,在哨兵选择出新master之前,这之间存在一段空白时间。这段空白时间内, master是不能存储数据的,所以有可能会出现数据的丢失。所以硬件允许条件下可以使用Redis集群(cluster)方案 。