为什么要有哨兵机制
redis主从架构中,主从模式是读写分离的,只有主服务器才能处理客户端的读操作,所以如果主节点挂了,就会没有主节点处理客户端的写操作,同时也没有主节点给从节点进行数据同步了
如果需要恢复服务的话,就需要在从节点中选出一个作为主节点并且让其他从节点重新指向新的主节点,并且通知上游客户端换了主节点需要更新为新主节点的ip地址
如果这些都由人工进行检测和故障转移的话非常费劲,所以就需要有一个能够检测主节点状态并且在主节点发生故障的时候进行故障转移的“哨兵”
Redis 2.8以后支持使用哨兵机制,其作用就是主从节点故障转移
哨兵集群
哨兵之间是如何发现的
在哨兵集群中,哨兵节点之间是通过redis的发布订阅机制来相互发现的
主节点上会有一个__sentinel__:hello
频道,哨兵会将自己的IP地址和端口信息发布到这个频道上,其他订阅了该频道的哨兵就可以直接获取到这个哨兵的IP地址和端口号,然后它们之间就会建立连接
哨兵是如何知道从节点信息的
从节点的信息会被保存在主节点中,哨兵会10秒发送一次INFO
命令给主节点获取从节点的信息,然后和从节点建立连接
哨兵机制是怎么工作的
哨兵是运行在独立于主从架构外的服务器中的redis进程,所以它也是一个节点,并且不参与主从架构中的读写操作,它就好像一个观察者,观察主从节点的状态,在发现异常之后及时做出处理
哨兵节点主要负责三件事:监控、选举、通知
监控
哨兵会每隔一秒给所有主从节点发送PING命令,正常运行情况下主从节点收到后会发送响应命令给哨兵
如果主从节点在规定时间内没有响应PING命令,则会被哨兵标记为[主观下线]
规定时间在配置项 down-after-milliseconds 参数设置,单位是毫秒
为什么哨兵必须以集群形式出现?
但是现在会有一个问题,主从节点在规定时间内没有响应,无法判断真的是主从节点挂了还是其他网络原因导致拥塞而响应慢了,或者是哨兵自己出现问题了,所以为了防止误判行为的发送,哨兵的部署不会只有一台,而是以哨兵集群的形式出现,并且哨兵集群中最少需要部署3台机器,这样能尽可能避免由于某台哨兵出现问题而导致误判情况的发生
客观下线
在一个哨兵将某个主节点标记为主观下线后,会告知其他哨兵,让其他哨兵也进行检测,判断是否下线并且投出认同和不认同票
当哨兵的认同票达到哨兵配置文件中quorum所配置的值时,主节点被标记为[客观下线],然后哨兵会在从节点中选举出新的主节点
quorum配置项的值应该设为多少才合理?
quorum 的值一般设置为哨兵个数的一半加一
redis哨兵采用奇数个存在
配置哨兵的个数需超过3,并且哨兵的个数都是以奇数个存在,原因有:
1.选主依赖投票 majority 出现问题时能做正确判断。
如果哨兵个数是偶数,发生分歧时将无法形成多数票,无法通过投票方式解决主节点选举问题。
2.提高可靠性。
如果哨兵个数为偶数,一半哨兵节点出现问题,将无法形成多数票进行监视和故障转移,系统可用性不高。而奇数个哨兵,可以容忍一半 moins 1 个节点异常,还能达成多数决。
3.防止 splits brain 问题。
如果哨兵分为两个组,每个组内节点数相同,这时如果两组节点在同一个时间点失联,将导致双主问题,数据不一致。奇数节点可以避免这种情况。
4.更易形成多数决定。
采用奇数哨兵比如3个或5个,出现问题时更容易泾渭分明,形成多数决定的一方,做出正确的选择。
选举
由谁来选举?
当主节点发送故障时,哨兵集群会进行主从的故障转移,会在哨兵集群中选出一个leader来进行主从切换
成为哨兵leader需要满足以下两个条件并且缺一不可:
-
获得的赞成票超过一半
-
获得的票数大于等于哨兵配置文件中的 quorum 值
相关例子
-
哨兵节点有 3 个,quorum 设置为 2,只有1个哨兵参与leader选举,获得2票以上成功选举,否则重新选举
-
哨兵节点有 3 个,quorum 设置为 2,有2个哨兵参与leader选举,每位候选者都会先给自己投一票,然后向其他哨兵发起投票请求。投票者先收到谁的投票请求,就会先投票给谁,用完投票机会后再次收到其他候选人的投票请求后会拒绝投票。
-
哨兵节点有2个,quorum 设置为 2,有2个哨兵挂了,无法选举leader
-
哨兵节点有3个,quorum 设置为 2,有2个哨兵挂了,候选者仍有机会获得2票,可以选举成功并且完成主从切换
-
哨兵节点有5个,quorum 设置为 3,有2个哨兵挂了,候选者仍有机会获得3票,可以选举成功并且完成主从切换
-
哨兵节点有5个,quorum 设置为 3,有3个哨兵挂了,无法判定主节点为“客观下线”,也无法完成主从切换
-
哨兵节点有5个,quorum 设置为 2,有3个哨兵挂了,可以判定主节点为“客观下线”,但是由于获得的赞成票无法超过一半,所以不能完成主从切换
故障转移
故障转移的过程
-
哨兵leader选出新的主节点
-
将从节点指向新的主节点
-
通知客户端更换了新的主节点
-
旧的主节点变更为从节点
详细过程
过程1:哨兵leader选出新的主节点
从节点选为新主节点排序规则:
1.过滤掉已经离线的
2.过滤掉历史网络连接状态不好的
看 down-after-milliseconds * 10
配置项,是主从节点断连的最大连接超时时间,发生断连超过10,说明网络状况不好
3.优先级,优先级越小排名越靠前
slave-priority
配置项可以配置优先级,可以根据服务器性能来配置
4.优先级相同,选复制进度最靠前的
主节点会用 master_repl_offset
记录当前的最新写操作在 repl_backlog_buffer
中的位置
从节点用slave_repl_offset
记录复制进度
选择从节点的 slave_repl_offset
最接近 主节点的 master_repl_offset
的从节点
5.优先级相同,复制进度相同,选ID号小的
每个从节点都有一个编号,这个编号就是 ID 号,是用来唯一标识从节点的
随后
向这个从节点发送 SLAVEOF no one
命令,转换成主节点,发送命令之后哨兵leader会1秒发送一次INFO
命令给新的主节点,没故障转移前是10秒发送一次,然后观察它回复的角色信息,由slave变为master的时候,主从切换成功
过程2:将从节点指向新的主节点
哨兵leader向所有从节点发送SLAVEOF
命令,使其成为新主节点的从节点
过程3:通知客户端更换了新的主节点
每个哨兵节点提供发布者/订阅者机制,客户端可以从哨兵订阅消息,订阅频道很多,不同频道包含了主从节点切换过程中的不同关键事件
客户端和哨兵建立连接后,客户端会订阅哨兵提供的频道
主从切换完成后,哨兵就会向 +switch-master
频道发布新主节点的 IP 地址和端口的消息,客户端会使用新主节点的 IP 地址和端口进行通信
不同频道的作用
通过发布者/订阅者机制机制,通过这些事件通知客户端可以在主从切换后得到新主节点的连接信息,还可以监控到主从节点切换过程中发生的各个重要事件,知道主从切换进行到哪一步了,有助于了解切换进度。
过程4:旧的主节点变更为从节点
哨兵集群会继续监视旧的主节点,重新上线后会向它发送SLAVEOF命令使其成为新主节点下的从节点