哨兵是特殊的Redis节点。哨兵可以实现主从节点的故障转移。它会监测主节点是否存活,如果主节点挂了,他会从从节点中选举出一个新的主节点,然后向其它的从节点和客户端通知新的主节点的信息
具体而言,哨兵会通过向主从节点发送ping命令,如果它们没有在规定的时间内响应,哨兵就会将它们标记为“主观下线”。实际上,没有返回相应可能是因为系统压力比较大或者网络发送了拥塞,并没有发生故障。为了减少误判,会使用一个哨兵集群。一个哨兵判断某个节点“主观下线”后,会通知其它哨兵对该节点的存活状态做出判断,只有规定数量quorum (一般是哨兵数量 / 2 + 1)的哨兵认为该节点下线,该节点才会被哨兵标记为“客观下线”
先选出一个候选者,谁收到的关于节点“主观下线”的赞成票数达到quorum 然后判断节点“客观下线”谁就是候选者。当然,可能存在多个节点同时判断节点“客观下线”,这时会多个候选者。
接着,再选出一个leader。每个候选者先给自己投一票,然后向其它哨兵发起投票请求,每个节点只能投出一次票,投过票之后其它节点来请求投票时会被拒绝。这样,率先达到半数以上的赞成票并且达到quorum 值的哨兵成为leader。选举出来leader,就可以进行主从故障转移了。
如果哨兵只有两个,那么如果其中一个节点挂了之后,就无法满足选举出leader的要求,赞成票超过半数以上(这里至少要2票)
当然,如果三个哨兵挂了两个,这时就需要认为介入了,或者增加多一些哨兵节点
选择标准:
首先过滤掉已经下线的从节点,然后评判剩下的从节点之前的网络状况。配置文件中有一个down-after-milliseconds * 10的配置项,如果主从节点在down-after-milliseconds时间内没有连接上,就可以认为主从节点断连了,而一旦这种情况超过十次,就说明这个从节点的网络状况不好,不适合作为新的主节点。
优先级的设置根据服务器的性能配置,可能会将物理内存大的优先级调高
如果某个从节点的 slave_repl_offset 最接近 master_repl_offset,说明它的复制进度是最靠前的,于是就可以将它选为新主节点。
选出一个合适的从节点后,哨兵leader对这个从节点发送SLAVEOF no one
命令,将该从节点转换为主节点。然后每秒向被升级的从节点发送info命令(每故障之前是每十秒一次),查看命令回复中的角色信息是否变成master。
leader向其它从节点发送slaveof命令,让它们指向新的主节点
通过发布订阅机制,leader向客户端发送主库地址变化的消息。
另外,通过发布订阅,客户端可以监控主从切换过程中发生的各个事件以及进度。
leader继续监视旧主节点的网络状况,当旧主节点重新上线时,leader向其发送slaveof命令,将其变为新的主节点的从节点。
哨兵集群中的哨兵之间是通过发布订阅的方式感知到对方的,哨兵向主节点的一个__sentinel__:hello
的频道发送自己的IP地址和端口信息,其它订阅了该频道的哨兵就可以获取该哨兵的信息,就可以与之建立连接了。