redis sentinel 工作原理
二 工作原理
2.1 Sentinel 构成
一个完整的sentinel集群包括两个部分:
-
哨兵节点(sentinel):负责监控redis和sentinel节点的运行情况。
-
数据节点:即redis节点,包含主从节点。
2.2 Sentinel 机制
redis使用(sentinel)的工作原理是:
-
redis使用一组sentinel节点来监控主从redis服务的可用性。
-
一旦监控发现redis主节点失效,将选举出一个哨兵节点作为领导者(leader)。
-
sentinel的领导者从剩余的从redis节点中选出一个redis节点作为新的主redis节点对外服务。
我们通过几个问题来深入了解其工作机制
-
1 如何监控各个节点?
-
2 如何确定redis节点失效?
-
3 如何选举一个sentinel的领导者?
-
4 如何切换?
2.3 如何监控
sentinel节点通过三个定时监控任务监控redis节点服务可用性。
sentinel 每隔10秒向集群redis数据节点发送info命令,获取新的拓扑结构信息。包括主从角色以及ip,port。如果有新增redis节点也会自动探测到新的拓扑结构。
向_sentinel_:hello频道同步信息
每个哨兵节点每隔2秒会向redis数据节点的sentinel:hello频道同步自身得到的主节点信息以及当前哨兵节点的信息,由于其他哨兵节点也订阅了这个频道,该操作可以交换哨兵节点之间关于主节点以及哨兵节点的信息。
该操作的功能有两个:
发现新的哨兵节点:如果有新的哨兵节点加入,此时保存下来这个新哨兵节点的信息,后续与该哨兵节点建立连接。
交换主节点的状态信息,作为后续客观判断主节点下线的依据。
向数据节点做心跳探测
sentinel节点每隔1秒向redis节点发送ping命令来检测实例的状态,如果在指定的时间内(down-after-milliseconds)没有回复或则返回错误的回复,那么该实例被判为下线。
这里需要特别说明两个状态SDOWN,ODOWN
主观下线 SDOWN:如果sentinel探测心跳任务在配置的down-after-milliseconds之后没有收到有效回复,那么就认为该数据节点主观下线(sdown)
客观下线 ODOWN:当一个哨兵节点认为主节点主观下线时,该哨兵节点需要通过 sentinelis-master-down-byaddr
命令向其他哨兵节点咨询该主节点是否下线了,如果有超过半数的哨兵节点都回答了下线,此时认为主节点客观下线。
选举sentinel的领导者
当主节点客观下线时,需要选举出一个sentinel节点做为领导者,以完成后续选出新的主节点的工作。
-
每个sentinel节点通过向其他节点发送”sentinel is-master-down-by addr”命令来申请成为领导者。
-
而每个sentinel节点在收到一个”sentinel is-master-down-by addr”命令时,只允许给第一个节点投票,其他节点的该命令都会被拒绝。
-
如果一个sentinel节点收到了半数以上的同意票,则成为sentinel领导者。
-
如果前面三步在一定时间内都没有选出一个sentinel领导者,将重新开始下一次选举。
选择新的主节点 在剩下的redis从节点中,按照以下顺序来选择新的主节点:
-
过滤掉“不健康”的数据节点:比如主观下线、断线的从节点、五秒内没有回复过哨兵节点ping命令的节点、与主节点失联的从节点。
-
选择slave-priority(从节点优先级)最高的从节点,如果存在则返回不存在则继续后面的流程。
-
选择复制偏移量最大的从节点,这意味着这个从节点上面的数据最完整,如果存在则返回不存在则继续后面的流程。
-
到了这里,所有剩余从节点的状态都是一样的,选择runid最小的从节点。
执行failover切换
-
sentinel向选为主节点的slave发送SLAVEOF NO ONE命令,提升该节点为主。
-
然后向其余redis节点发送slaveof 命令使之成为新主的从库节点。
-
哨兵节点集合会将原来的主节点更新为从节点,当其恢复之后命令它去复制新的主节点的数据。
因为redis采用的是异步复制,没有办法避免数据的丢失。但可以通过以下配置来使得数据不会丢失:min-slaves-to-write 1 、 min-slaves-max-lag 10。一个redis无论是master还是slave,都必须在配置中指定一个slave优先级。要注意到master也是有可能通过failover变成slave的。如果一个redis的slave优先级配置为0,那么它将永远不会被选为master,但是它依然会从master哪里复制数据。
通过上面的分析,我们已经直接回答了上面的四个问题。接下来我们根据切换日志再熟悉一下sentinel的工作流程吧。
2.4 failover 日志分析
sentinel 节点
-
qabb-qa-mysql0 10.215.20.24 26379
-
qabb-qa-mysql1 10.215.20.19 26379
-
qabb-qa-mysql2 10.215.20.7 26379
redis 主从关系
-
qabb-qa-mysql0 10.215.20.24 6379 从库
-
qabb-qa-mysql1 10.215.20.19 6379 主库
-
qabb-qa-mysql2 10.215.20.7 6379 从库
主动将主库关闭,观察sentinel的切换过程。
-
27 Jan 21:31:10.398 # +sdown master mymaster 10.215.20.19 6379 ##进入主观不可用(SDOWN)
-
27 Jan 21:31:10.456 # +odown master mymaster 10.215.20.19 6379 ##quorum 3/2 ##超过半数投票达到了quorum,客观不可用(ODOWN)
-
27 Jan 21:31:10.456 # +new-epoch 3 ##更新当前配置版本为3 ,之前切换过2次测试
-
27 Jan 21:31:10.456 # +try-failover master mymaster 10.215.20.19 6379 ##达到failover条件,正等待其他sentinel的选举
-
27 Jan 21:31:10.470 # +vote-for-leader 67b1eb6fa5fba3c927c027c1bb60b1890c23f330 3 ##投票选举
-
27 Jan 21:31:10.471 # b57983116e92a089ab7fff22584c1aaa128d83b8 voted for b57983116e92a089ab7fff22584c1aaa128d83b8 3 ##投票选举
-
27 Jan 21:31:10.488 # 966c26050372456aae216d7e5d82fff300d73c61 voted for 67b1eb6fa5fba3c927c027c1bb60b1890c23f330 3 ##投票选举
-
27 Jan 21:31:10.553 # +elected-leader master mymaster 10.215.20.19 6379 ##准备进行failover 切换
-
27 Jan 21:31:10.553 # +failover-state-select-slave master mymaster 10.215.20.19 6379
-
27 Jan 21:31:10.609 # +selected-slave slave 10.215.20.24:6379 10.215.20.24 6379 @ mymaster 10.215.20.19 6379 ##选择10.215.20.24为新主库
-
27 Jan 21:31:10.609 * +failover-state-send-slaveof-noone slave 10.215.20.24:6379 10.215.20.24 6379 @ mymaster 10.215.20.19 6379 ##执行slaveof no one
-
27 Jan 21:31:10.685 * +failover-state-wait-promotion slave 10.215.20.24:6379 10.215.20.24 6379 @ mymaster 10.215.20.19 6379
-
27 Jan 21:31:11.663 # +promoted-slave slave 10.215.20.24:6379 10.215.20.24 6379 @ mymaster 10.215.20.19 6379 ##选举为主库
-
27 Jan 21:31:11.663 # +failover-state-reconf-slaves master mymaster 10.215.20.19 6379 ###failover状态变为reconf-slaves
-
###sentinel将10.215.20.7 指向新主库
-
27 Jan 21:31:11.733 * +slave-reconf-sent slave 10.215.20.7:6379 10.215.20.7 6379 @ mymaster 10.215.20.19 6379
-
27 Jan 21:31:12.320 * +slave-reconf-inprog slave 10.215.20.7:6379 10.215.20.7 6379 @ mymaster 10.215.20.19 6379
-
27 Jan 21:31:12.320 * +slave-reconf-done slave 10.215.20.7:6379 10.215.20.7 6379 @ mymaster 10.215.20.19 6379
-
##failover成功完成
-
27 Jan 21:31:12.378 # +failover-end master mymaster 10.215.20.19 6379
-
27 Jan 21:31:12.378 # +switch-master mymaster 10.215.20.19 6379 10.215.20.24 6379 ##master的地址发生变化
-
27 Jan 21:31:12.379 * +slave slave 10.215.20.7:6379 10.215.20.7 6379 @ mymaster 10.215.20.24 6379
-
27 Jan 21:31:12.379 * +slave slave 10.215.20.19:6379 10.215.20.19 6379 @ mymaster 10.215.20.24 6379
-
27 Jan 21:31:42.476 # +sdown slave 10.215.20.19:6379 10.215.20.19 6379 @ mymaster 10.215.20.24 6379 ##原主进入主观不可用状态
从日志上可以观察到 进过 down-after-milliseconds=30000ms 也就是30秒之后老的主库进入不可用状态。如果重新启动老的主库会如下日志 ,sentinel将老的主库离开主观不可用状态,并且重新加入到主从复制关系,并指向新的主库。
-
27 Jan 2020 22:16:48.692 # -sdown slave 10.215.20.19:6379 10.215.20.19 6379 @ mymaster 10.215.20.24 6379
-
27 Jan 2020 22:16:58.631 * +convert-to-slave slave 10.215.20.19:6379 10.215.20.19 6379 @ mymaster 10.215.20.24 6379
三 小结
通过两篇文章 算是对redis sentinel 高可用机制有了深入浅出的理解和认识。另外留个尾巴业务方如何介入 redis sentinel的 ,如何做到更平滑的切换。