Redis哨兵故障转移
下线标记
Sentinel定期向Master节点发送PING
命令,若在限定时间内没有收到有效回复,则会将该节点状态中的flags字段设为SRI_S_DOWN
,即标记为主观下线状态,同时尝试向其他Sentinel询问节点状态。
Sentinel使用:
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
来询问其他Sentinel是否同意主服务器已下线,其他Sentinel按照以下格式回复:
1) <down_state>
2) <leader_runid>
3) <leader_epoch>
若down_state为1,则说明同意下线状态。
当有足够的Sentinel同意下线数量,Sentinel会将该Master节点状态中的flags字段设为SRI_O_DOWN
,表示进入客观下线状态。
选举领头Sentinel
当有Master节点被标记为客观下线,监视这个下线Master节点的各个Sentienl会进行协商,选举领头Sentinel进行故障转移操作。
所有的该Master节点的Sentinel都有被选为领头节点的资格。每次选举中不管是否成功,Sentinel配置中的纪元epoch都要加1。
在每个epoch内,各个Sentinel都可能成为领头,局部领头一旦设置,在当前epoch内就不能改变。
每个发现Master节点进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部领头Sentinel。当一个Sentinel向对方发送is-master-down-by-addr
命令且ip参数为*
时,即表示希望对方将自己设置为领头。设置规则为先到先得,后续的申请都会被拒绝。对方收到申请后会响应命令回复,回复中的leader_runid和leader_epoch分别记录了局部领头的运行id和配置纪元。源Sentinel会判断对方响应的runid和epoch是否与自己对应,如果对应则说明对方将自己设置为局部领头。当某个Sentinel被半数以上的Sentinel设置为局部领头,那么这个Sentinel成为领头Sentinel。
如果在时限内没有Sentinel拿到半数以上投票,则开始一个新的纪元重新进行选举。
故障转移
领头Sentinel确定后,领头Sentinel对下线的Master节点进行故障转移:
- 从下线Master节点的从服务器中挑选一个转为主服务器
- 让已经下线的节点的从服务器改为复制新的主服务器
- 将已经下线的节点设置为新的Master的从服务器
选择新Master服务器按照如下规则逐步过滤:
- 删除已经下线的从服务器
- 删除最近5秒内没有回复过领头Sentinel的INFO命令的从服务器
- 删除与已下线主服务器断开连接超过
down-after-milliseconds
* 10毫秒的从服务器,以保证从服务器没有过早与主服务器断开连接 - 根据从服务器的优先级进行排序,优先级相同则按照复制偏移量排序,最后按照runid进行排序
Sentinel向新选出的主服务器发送slaveof no one
命令,并且持续发送INFO
命令观察服务器的角色是否从role变为master。
当新Master的角色改变后,Sentinel向其他从服务器发送slaveof
命令使他们复制新的主服务器。
当旧的Master上线后,Sentinel也会向它发送slaveof
命令,让他成为从服务器。