Redis哨兵(sentinel)
吹哨人巡査监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库,继续对外服务。
1. 哨兵的作用
- 不存放数据,监控redis运行状态是否正常,包括master和slave
- 当master down机,能自动将slave切换成新master
- 客户端通过连接哨兵来获得当前Redis服务的主节点地址
- 哨兵可以将故障转移的结果发送给客户端
2. 集群设计
角色 | 主 | 从 | 哨兵 |
---|---|---|---|
机器 | mysql01 | mysql02 | mysql01,mysql02 |
建议哨兵搭建至少2个,避免单个哨兵网络抖动等原因主观误判导致主从切换反而出现问题。
3. Redis哨兵搭建
3.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
重要参数说明:
- 设置要监控的master服务器,格式为
sentinel monitor <master-name> <ip> <redis-port> <quorum>
, 具体配置中mymaster是主节点的名字,192.168.154.141为初始化master的ip,6379为端口,2表示确认客观下线的最少的哨兵数量。 - 设置连接master的认证密码,格式为
sentinel auth-pass <master-name> <password>
。表示为连接master服务器的用户密码。 - 设置连接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. 测试故障转移
- 手动关闭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的日志: 可以看到从节点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 哨兵启动
- 哨兵启动后会拿着用户密码信息连接master节点,通过发布/订阅主库的
__sentinel__:hello
频道, 实现哨兵之间发现和通信。发布自己的节点消息,订阅该频道其他哨兵消息。消息内容为下图,还通过通过info命令得到从节点的信息,包括从节点列表、复制状态等 - 哨兵之间建立连接后,会对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下线
- 当master失效后,单个sentinel检测到的关于master的状态,就是从sentinel的角度来看如果发送了PING心跳后,一定时间内没有收到合法的回复,就认为是SDown主观下线(Subjectively Down)。
- 当Sentinel节点将主节点标记为主观下线(SDOWN)后,就立即向其他Sentinel节点发送询问,确认主节点是否真的下线。如果多个哨兵达成一致意见(前面配置quorum数量)才能认为一个master客观上已经宕掉,此时就认为是ODown客观下线(Objectively Down)。
8.3 哨兵进行故障转移
- 当主节点被判断客观下线以后,各个哨兵节点会进行协商选举(Raft算法)出一个Sentinel leader(哨兵领导者)节点并由该领导者节点进行failover(故障迁移)。
- 哨兵领导者会进行按照如下master规则从slave节点列表中选出master。
- Sentinel leader会对选举出的新master进行
slaveof no one
命令,将其提升为master。 - Sentinel leader向对其他slave节点发送命令,让剩余的slave成为新master主节点的slave。
- 如果后面老master重新上线后,它会成为新master的从节点,从而恢复正常工作。
上述failover(故障迁移)操作均由sentinel本身自动完成,无需人工干预。
9. 哨兵的使用建议
- 哨兵节点的数量应为多个。哨兵本身应该是集群,保证高可用。
- 哨兵节点的个数应该为奇数。
- 各个哨兵的配置保持一致,包括服务器硬件设备。以免影响公平的投票机制。
- 如果哨兵节点部署在Docker等容器上,一定要保证端口的正确映射。
- 哨兵集群+主从复制方案并不能保证数据的零丢失。由于只有一台master ,当master宕机之后,在哨兵选择出新master之前,这之间存在一段空白时间。这段空白时间内, master是不能存储数据的,所以有可能会出现数据的丢失。所以硬件允许条件下可以使用Redis集群(cluster)方案 。