Redis的哨兵模式详解
# 哨兵模式的作用
哨兵提供以下几种功能
监控(Monitoring):哨兵会监控主节点和从节点是否正常运作。自动故障转移(Automatic failover):当主节点因为以外下线了,哨兵就会从从节点中选出新的主节点,并让其他从节点复制新的主节点的数据。通知(Notification):哨兵会将故障转移结果通知给客户端。配置提供者(Configuration provider):客户端连接redis时,会通过哨兵获取服务提供者。
# 实践1-基于Linux部署redis-sentinel
我们先基于Linux简单的部署一个redis-sentinel,通过三个哨兵监控一主二从的架构搭建一个简单的redis-sentinel,为了方便演示,这里所有redis都在同一台服务器中,通过端口号进行区分。

# 编辑哨兵配置文件
在配置哨兵之前,我们先通过客户端查看6379的redis的基本信息,可以看到当前6379身份为master,并且有两个从节点6380和6381。
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
# 两个从节点
slave0:ip=127.0.0.1,port=6380,state=online,offset=3082,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=3082,lag=0
2
3
4
5
6
7
8
9
10
了解了当前主从情况之后,我们就可以创建一个名为sentinel1.conf的哨兵配置文件,监控6379端口的节点。其余连个哨兵节点配置同理,只不过端口号改为26380和26381即可。
# 哨兵端口号为26379
port 26379
# 监控6379端口号的节点
sentinel monitor master_redis 127.0.0.1 6379 1
2
3
4
# 启动哨兵
通过下面的三条命令启动三个哨兵,完成命令且没有报错后,我们可以通过ps命令查看哨兵是否都正常启动,确保无误,我们再进入下一步。
redis-sentinel /root/redis/conf/sentinel1.conf
redis-sentinel /root/redis/conf/sentinel2.conf
redis-sentinel /root/redis/conf/sentinel3.conf
2
3
# 手动杀死master
我们在服务器中定位到master的redis进程,使用kill命令将其杀死,此时我们观察哨兵的日志就会看到它们进行故障转移,由此说明我们的哨兵模式架构部署成功。
8210:X 29 Aug 2022 01:01:59.772 # +failover-end master master_redis 127.0.0.1 6379
8210:X 29 Aug 2022 01:01:59.772 # +switch-master master_redis 127.0.0.1 6379 127.0.0.1 6380
2
# 实践2-基于docker容器建立redis-sentinel
基于docker容器部署并在Spring Boot中实践的案例碍于篇幅的原因,笔者这里就不展开了,感兴趣的读者可以参考笔者的这篇文章:
Docker图形化界面工具Portainer最佳实践 (opens new window)
# 理论
# 哨兵节点如何与主从库建立联系
首先每个哨兵都在主库的__sentinel__:hello频道和其他哨兵建立连接,构成一张网络,使得彼此都在master网络进行通信。

然后哨兵通过info命令从主库中获取从库的信息,从而与master相关联的从库建立联系,此时一个redis-sentinel网络就完全构建完成了。

# 哨兵如何判断master下线
先主观下线,任意一个哨兵对主节点进行检测判断,主节点是否下线。
然后触发客观判定下线了,哨兵集群通过投票判定当前主节点是否下线,其工作过程如下:
- 某个哨兵主观判定主节点下线,向其他哨兵发出
is-master-down-by-addr,开始对是否下线判定进行投票 - 每个哨兵发出自己的看法
- 根据
sentinel monitor <master-name> <ip> <redis-port> <quorum>设置quorum,若同意数大于等于quorum则判定主节点下线。

# 哨兵集群如何选举出leader
判定主库下线后我们就必须选出哨兵中的leader找下一个主节点,所以我们必须建立一个哨兵集群,这个哨兵集群我们必须从中选举出leader作为哨兵leader,而哨兵选举出的leader必须符合以下两个条件:
num(total_sentinels)/2+1即半数(所有哨兵数的半数,无论哨兵死活)以上的选票即可成为哨兵中的leader,这就是著名的Raft算法- 选票数还必须大于等于
quorum
# 假如我们当前有5个哨兵,1个主节点,3个从节点,quorum设置为2。假如此时有3个哨兵挂掉,请问我们可以判定主节点下线以及选举新的主节点嘛?
首先解决第一个问题,由于哨兵挂了3个所以还剩两个,假如主节点挂了,由于quorum等于2,所以我们有一定概率(两个哨兵都认为主节点挂了)判定主节点下线。
再来说说第2个问题,上文已经给出了选举新的哨兵leder的两个条件,本题目明显不符合条件1,因为(5/2)+1=3,而哨兵只剩两个了,所以选不出哨兵的leader,也就没办法指定新的leader了。
# 哨兵是如何选举主节点
遵循下面三个原则:
- 过滤掉不健康的即哨兵
ping不同的从节点 - 选择
slave-priority从节点优先级高的 - 如果不存在
slave-priority配置,则选择复制偏移量(即永远原来master最多数据的节点)最大,作为主节点 - 如果还不存在,这选择
runid最小的值作为主节点(即最新启动的从节点)

总结一下:
- 选举出哨兵
leader。 - 哨兵
leader根据上文规则选出新的master。 - 从节点复制新
leader的数据。 - 通知客户端主节点更换。
- 若原来的主节点复活,则作为新主节点的从节点。
# 参考文献
Redis进阶 - 高可用:主从复制详解 (opens new window) Redis进阶 - 高可用:哨兵机制(Redis Sentinel)详解 (opens new window)