Appearance
Redis 哨兵
本文介绍有关Redis哨兵监控相关知识。
1. 概述
在非Redis集群环境下,哨兵(Sentinel)可以为Redis提供高可用。主要作用如下:
- 监控:哨兵可以不时检测Redis主从节点是否正常工作;
- 通知:当被监控的Redis实例出问题时,哨兵可以发出通知;
- 自动故障恢复:如果Redis主节点意外下线,哨兵可以启动自动故障恢复流程:选取一个从节点,将其提升为主节点,其他从节点自动重新配置跟随新的主节点,使用Redis的应用程序也会得到通知使用新的主节点;
- 配置提供者:客户端连接到哨兵实例,查询负责特定服务的当前 Redis 主服务器的地址。如果发生故障转移(failover),哨兵会告知客户端新的主服务器地址。
2. 哨兵配置与启动
Sentinel配置文件下载地址:https://download.redis.io/redis-stable/sentinel.conf
Sentinel相关配置项如下:
port 26379:配置哨兵端口;logfile xxx:配置日志文件;sentinel monitor <master-name> <ip> <redis-port> <quorum>:设置哨兵监控的主节点<master-name>:主节点名称,自己取,例如mymaster;<ip>:主节点IP地址;<redis-port>:主节点端口;<quorum>:它用于指定在主节点(master)发生故障时,至少需要多少个哨兵实例同意主节点确实不可用,才能进行自动故障转移(failover)操作。
sentinel auth-pass <master-name> <password>:设置哨兵节点访问主节点的密码;<master-name>:主节点名称,与上面的相同;<password>:主节点密码;
一份示例sentinel.conf文件如下:
txt
port 26379
logfile "/redis-sentinel/sentinel.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 123456有以下两种方式启动哨兵:
方式一:使用
redis-sentinelbashredis-sentinel /path/to/sentinel.conf方式二:使用
redis-serverbashredis-server /path/to/sentinel.conf --sentinel
本次使用Docker启动sentinel,请参考资料2。
启动命令如下:
txt
docker run --name redis-sentinel \
-v /path/to/redis-sentinel/persistence:/bitnami \
-p 26379:26379
bitnami/redis-sentinel:latestbitnami/redis-sentinel镜像会在/bitnami/redis-sentinel/conf/路径寻找配置文件,所以我们可以挂载宿主机目录到该路径。例如:
/projects/docker/sentinel01:并在该路径下的/redis-sentinel/conf/存放着有sentinel.conf配置文件。
3. 测试案例
3.1 一主二从结构
我们先使用Docker启动一主二从Redis实例。
DANGER
注意,由于主节点有可能变为从节点,从节点也有可能变成主节点,所以所有的主从节点都需要配置下面的选项:
txt
requirepass 123456
masterauth 123456并且,主从节点的密码都要相同。
配置结果如下:

3.2 启动哨兵节点
启动三个哨兵节点,监听26379端口,分别映射到宿主机26379,26380,26381端口。哨兵节点配置如下:
txt
port 26379
logfile "/bitnami/redis-sentinel/sentinel.log"
sentinel monitor mymaster 172.17.0.2 6379 2
sentinel auth-pass mymaster 123456结果如下:

3.3 主节点下线
关闭主节点所在容器,模拟主节点下线,然后,分别在三个节点的命令行界面查看信息:

可以发现:
- 其中一台从节点上位成为新的主节点;
- 其他的从节点跟随新的主节点;
3.4 原主节点重新上线
我们重新启动原主节点,发现原主节点成为了从节点,跟随新的主节点:

4. 原理解析
哨兵监控主要靠修改配置文件工作。
4.1 哨兵启动
三个哨兵节点依次启动,相关日志如下:
txt
1:X 11 Jun 2025 03:03:13.048 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:X 11 Jun 2025 03:03:13.048 * Redis version=7.4.3, bits=64, commit=00000000, modified=1, pid=1, just started
1:X 11 Jun 2025 03:03:13.048 * Configuration loaded
1:X 11 Jun 2025 03:03:13.049 * monotonic clock: POSIX clock_gettime
1:X 11 Jun 2025 03:03:13.049 * Running mode=sentinel, port=26379.
1:X 11 Jun 2025 03:03:13.050 * Sentinel new configuration saved on disk
1:X 11 Jun 2025 03:03:13.050 * Sentinel ID is 800e08c17595edb6b8e3ce0a89d5134ac15ba826
1:X 11 Jun 2025 03:03:13.050 # +monitor master mymaster 172.17.0.2 6379 quorum 2
1:X 11 Jun 2025 03:03:13.051 * +slave slave 172.17.0.3:6379 172.17.0.3 6379 @ mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:03:13.052 * Sentinel new configuration saved on disk
1:X 11 Jun 2025 03:03:13.052 * +slave slave 172.17.0.4:6379 172.17.0.4 6379 @ mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:03:13.053 * Sentinel new con figuration saved on disk
1:X 11 Jun 2025 03:03:43.053 * +sentinel sentinel 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 172.17.0.6 26379 @ mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:03:43.054 * Sentinel new configuration saved on disk
1:X 11 Jun 2025 03:04:05.373 * +sentinel sentinel 7b59165baed59b231fd9fa5c926284adf9f6a907 172.17.0.7 26379 @ mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:04:05.377 * Sentinel new configuration saved on disk主要记录了以下几件事:
- 监测到Redis节点正在运行,如第1行;
- 为该哨兵节点创建一个ID:Sentinel ID,如第7行 ;
- 检测到从节点,如第9-12行;
- 其他哨兵启动,监测到其他哨兵节点,如第13-16行;
4.2 启动时记录配置信息
在哨兵节点启动时,在日志中有很多下面的记录:
txt
Sentinel new configuration saved on disk这句话的意思是会在哨兵节点配置文件sentinel.conf中记录相关配置信息,如:
txt
# Generated by CONFIG REWRITE
protected-mode no
latency-tracking-info-percentiles 50 99 99.9
dir "/"
user default on nopass sanitize-payload ~* &* +@all
sentinel myid 8c8ab9eb52610693bf699f29f1f7f58483f89f5e
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel current-epoch 1
sentinel known-replica mymaster 172.17.0.3 6379
sentinel known-replica mymaster 172.17.0.4 6379
sentinel known-sentinel mymaster 172.17.0.7 26379 7b59165baed59b231fd9fa5c926284adf9f6a907
sentinel known-sentinel mymaster 172.17.0.5 26379 800e08c17595edb6b8e3ce0a89d5134ac15ba826主要关注三方面:
- 记录本哨兵ID,如第6行;
- 记录从节点地址,如第11-12行;
- 记录其他哨兵地址和ID,如第14-15行;
4.3 主节点下线
当主节点下线后,查看哨兵节点日志:
txt
1:X 11 Jun 2025 03:05:36.312 # +sdown master mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:05:36.332 * Sentinel new configuration saved on disk
1:X 11 Jun 2025 03:05:36.333 # +new-epoch 1
1:X 11 Jun 2025 03:05:36.334 * Sentinel new configuration saved on disk
1:X 11 Jun 2025 03:05:36.334 # +vote-for-leader 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 1
1:X 11 Jun 2025 03:05:36.387 # +odown master mymaster 172.17.0.2 6379 #quorum 3/2
1:X 11 Jun 2025 03:05:36.388 * Next failover delay: I will not start a failover before Wed Jun 11 03:11:36 2025
1:X 11 Jun 2025 03:05:37.671 # +config-update-from sentinel 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 172.17.0.6 26379 @ mymaster 172.17.0.2 6379
1:X 11 Jun 2025 03:05:37.673 # +switch-master mymaster 172.17.0.2 6379 172.17.0.3 6379
1:X 11 Jun 2025 03:05:37.674 * +slave slave 172.17.0.4:6379 172.17.0.4 6379 @ mymaster 172.17.0.3 6379
1:X 11 Jun 2025 03:05:37.675 * +slave slave 172.17.0.2:6379 172.17.0.2 6379 @ mymaster 172.17.0.3 6379
1:X 11 Jun 2025 03:05:37.685 * Sentinel new configuration saved on disk如果某个哨兵 在指定时间(down-after-milliseconds)内未收到主节点的 PING 响应,则认为该节点主观下线。这称为主观下线(Subjectively Down,即sdown)。如第1行。
当某个哨兵认为主节点不可用时,通过通过发布/订阅机制通知其他哨兵,检测主节点状态,如果此时主节点真的下线了,sdown的哨兵数超过
quorum,则认为主节点客观下线(Objectively Down,即odown)了。从主观下线,到客观下线,是为了避免网络抖动等原因,使得单台哨兵节点未接收到主节点响应,误以为主节点下线从而发起故障恢复,只有哨兵集群中多数哨兵认为主节点下线了,才可以发起故障恢复。
即主观下线是一台哨兵节点的判断,不可靠;客观下线是哨兵集群的判断,可靠。
哨兵集群进行领导者选举,选择一个哨兵 负责执行故障转移:
领导者哨兵选举日志如下:
txt1:X 11 Jun 2025 03:05:36.331 # +vote-for-leader 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 1 1:X 11 Jun 2025 03:05:36.334 * 800e08c17595edb6b8e3ce0a89d5134ac15ba826 voted for 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 1 1:X 11 Jun 2025 03:05:36.335 * 7b59165baed59b231fd9fa5c926284adf9f6a907 voted for 8c8ab9eb52610693bf699f29f1f7f58483f89f5e 1该日志就是
9f5e这个哨兵的日志,首先第一行表示自己给自己投票,后面两行表示其他哨兵也投票给自己,所以该哨兵称为领导者。选择其中某个从节点作为主节点,使用命令
replicaof no one,并且将这个从节点的配置文件中有关从属关系配置删除;其他从节点跟随新的主节点,使用命令
replicaof <host> <port>,修改这些从节点的配置文件,改为新的主节点;修改原主节点的配置文件,使其跟随新的主节点;
哨兵节点也要更新相关配置,更新从节点信息。
4.4 原主节点重新上线
由于更改了配置文件,原主节点重新上线,也就成为了从节点。
5. 相关算法
5.1 领导者选举算法
领导者选举算法,主要是使用了Raft算法的变种。主要流程如下:
发起选举:
- 当某个哨兵发现主节点已经客观下线后,它会尝试发起一次领导者选举;
- 该哨兵会将自己的
epoch加 1,并向其他哨兵发送命令,请求它们投票给自己,表明自己想成为 Leader;
投票过程:
每个哨兵在一个
epoch内只能投一票。当一个哨兵 收到投票命令时:
- 如果它尚未在当前
epoch内投过票,并且请求投票的哨兵的epoch大于或等于自己的epoch,那么它会同意投票给请求者; - 它会将自己结构体中的
leader和leader_epoch字段更新为投票给的哨兵和其epoch。 - 如果它已经投过票给其他哨兵,或者请求者的
epoch小于自己的epoch,它将拒绝投票。
请求投票的哨兵收到其他哨兵的投票后,会记录这些投票。
- 如果它尚未在当前
Leader 选举成功:
- 如果一个哨兵收到了超过半数的哨兵投票,它就被选举为 Leader。
- 一旦选举出 Leader,该 Leader就负责执行后续的故障转移流程。
5.2 从节点提升算法
如果有多个从节点,哨兵领导者如何从多个从节点中选出一个,使其成为主节点呢?
首先,在配置文件
redis.conf中,replica-priority配置项的值越低,优先级越高;如果
replica-priority的值为0,则表示该从节点不会被选为主节点。如果优先级相同,则
Replication Offset越大的从节点,则表示其从主节点接收并执行到的命令越多,数据一致性更好,应该被选择;经过上面两步,仍然有多个从节点满足条件,则具有较小的
Run ID的从节点应该被选择。
6. 注意事项
- 哨兵节点的数量应为多个,保证高可用;
- 哨兵节点的数量应为奇数;
- 各个哨兵节点的配置应该相同,包括物理配置;
- 哨兵集群+主从复制的架构,并不能保证数据零丢失;
参考资料
[1] redis sentinel:https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/
[2] bitnami redis-sentinel:https://hub.docker.com/r/bitnami/redis-sentinel