Redis cluster 从库自动failover需要两轮投票的分析

从库自动failover,有三种情况

1.由存活的主节点判断挂掉的主节点为客观下线(fail),即其他主节点抢先收集够了pfail数,然后广播fail信息到从库,从库clusterCron检查到挂掉主库的fail并发起投票时,其他主节点会正常投票

从库的日志是:

76803:S 09 Jun 12:21:09.240 * FAIL message received from bb7664a96fc83d3f31c2649ec37894a4944ed38b about 64cdc10096644b5bc3624f41ade916983806c47c
76803:S 09 Jun 12:21:09.257 # Start of election delayed for 579 milliseconds (rank #0, offset 30).
76803:S 09 Jun 12:21:09.859 # Starting a failover election for epoch 37.
76803:S 09 Jun 12:21:09.860 # Failover election won: I'm the new master.
76803:S 09 Jun 12:21:09.860 # configEpoch set to 37 after successful failover
76803:M 09 Jun 12:21:09.860 * Discarding previously cached master state.

2.从库抢先判断为客观下线,即从节点抢先收集够了pfail数,从库将挂掉的主库提升为fail状态,但从库不会广播fail状态,所以无法将fail通知其他存活主库

从库的日志是:

83548:S 08 Jun 14:28:02.202 * Marking node 82f42d2e50fa857fcda87127c3b958f868328eaa as failing (quorum reached).
83548:S 08 Jun 14:28:02.207 # Start of election delayed for 856 milliseconds (rank #0, offset 28148706874).
83548:S 08 Jun 14:28:03.109 # Starting a failover election for epoch 6.

所以又会分为两种切换情况:
2.1如果delayed for 856 milliseconds后,其他主库的下线报告链表还没凑够,即其他主库对于挂掉主库的判断还没有转为fail,那么其他主库会拒绝投票,从库failover失败;
2.2如果delayed for 856 milliseconds后,其他主库的下线报告链表也凑够了,即其他主库对于挂掉主库的判断已经转为fail了,那么其他主库会投票,(当然这里也要有大多数的主节点凑够下线报告链表才行)。

从库自动failover第一轮投票失败的例子

master:
192.168.0.105:2222   挂掉的主库
192.168.0.105:3333
192.168.0.105:4444
slave:
192.168.0.106:2222  
192.168.0.106:3333
192.168.0.106:4444

1.从库2222 发现 主库2222主库挂了

76803:S 09 Jun 17:00:49.222 # Connection with master lost.

2.30秒后,识别pfail的先后顺序:
–从库2222 将 主库2222 设为pfail状态(主观下线),failures=0(因为从库的下线报告不会纳入计算),从库2222 中 主库2222 的flags=CLUSTER_NODE_PFAIL

76803:S 09 Jun 17:01:19.274 . *** NODE 64cdc10096644b5bc3624f41ade916983806c47c possibly failing

–主库3333 将 主库2222 设为pfail状态(主观下线),failures=1,主库3333 中 主库2222 的flags=CLUSTER_NODE_PFAIL

76879:M 09 Jun 17:01:19.354 . *** NODE 64cdc10096644b5bc3624f41ade916983806c47c possibly failing

–主库4444 将 主库2222 设为pfail状态(主观下线),failures=1,主库4444中 主库2222 的flags=CLUSTER_NODE_PFAIL

77004:M 09 Jun 17:01:19.395 . *** NODE 64cdc10096644b5bc3624f41ade916983806c47c possibly failing

3.从库2222 ping 主库4444,收到了来自 主库4444 的关于 主库2222 的下线报告,从库的failures=1,从库2222 中 主库2222 的flags=CLUSTER_NODE_PFAIL

76803:S 09 Jun 17:01:19.676 . Pinging node e353bf55e229998bc77408b5b0fe8194cbcd2c99
...
76803:S 09 Jun 17:01:19.677 - Node e353bf55e229998bc77408b5b0fe8194cbcd2c99 reported node 64cdc10096644b5bc3624f41ade916983806c47c as not reachable.

4.从库2222 ping 主库3333,收到了来自 主库3333 关于 主库2222 的下线报告,从库failures=2,从库2222 中 主库2222 的flags=CLUSTER_NODE_PFAIL

76803:S 09 Jun 17:01:20.680 . Pinging node bb7664a96fc83d3f31c2649ec37894a4944ed38b
...
76803:S 09 Jun 17:01:20.681 - Node bb7664a96fc83d3f31c2649ec37894a4944ed38b reported node 64cdc10096644b5bc3624f41ade916983806c47c as not reachable.

5.从库2222 收到两个主库的pfail,从库的下线报告连接failures大于(3/2+1),转为客观下线,从库2222 中 主库2222 的flags=CLUSTER_NODE_FAIL

76803:S 09 Jun 17:01:20.681 * Marking node 64cdc10096644b5bc3624f41ade916983806c47c as failing (quorum reached).

6.从库2222 在clusterCron时发现自己维护的 主库2222 的flags=CLUSTER_NODE_FAIL,所以开始制定投票计划

76803:S 09 Jun 17:01:20.781 # Start of election delayed for 801 milliseconds (rank #0, offset 86).

7.从库2222 发起投票

76803:S 09 Jun 17:01:21.583 # Starting a failover election for epoch 44.

8.两个存活主库收到投票请求,但拒绝投票,因为:

–此时 主库3333 只有自己的pfail,所以不敢断定挂掉的主库挂了,保守认为它还没挂

76879:M 09 Jun 17:01:21.572 # Failover auth denied to 3f81377c4930f5a90479e6ec2f93941e00c5ad67: its master is up

–此时 主库4444 只有自己的pfail,所以不敢断定挂掉的主库挂了,保守认为它还没挂

77004:M 09 Jun 17:01:21.572 # Failover auth denied to 3f81377c4930f5a90479e6ec2f93941e00c5ad67: its master is up

9.在拒绝投票之后,存活主库才收到了各自的下线报告,所以failures足够了,判定为客观下线

–主库4444 收到 主库3333 的下线报告,主库4444 给 主库2222 维护的下线报告链表的failures=2,设为客观下线,在此以后才可以投票给从库

77004:M 09 Jun 17:01:22.964 - Node bb7664a96fc83d3f31c2649ec37894a4944ed38b reported node 64cdc10096644b5bc3624f41ade916983806c47c as not reachable.
77004:M 09 Jun 17:01:22.964 * Marking node 64cdc10096644b5bc3624f41ade916983806c47c as failing (quorum reached).

–主库3333 收到 主库4444 的下线报告,主库3333 给 主库2222 维护的下线报告链表的failures=2,设为客观下线,在此以后才可以投票给从库

76879:M 09 Jun 17:01:22.964 - Node e353bf55e229998bc77408b5b0fe8194cbcd2c99 reported node 64cdc10096644b5bc3624f41ade916983806c47c as not reachable.
76879:M 09 Jun 17:01:22.964 * Marking node 64cdc10096644b5bc3624f41ade916983806c47c as failing (quorum reached).

10.由于第一轮投票两个主库都拒绝了,所以从库一直拿不够票数,无法执行切换操作,直到投票超时(60秒)

76803:S 09 Jun 17:02:21.618 # Currently unable to failover: Failover attempt expired.

11.第一轮投票失败后,从库2222 等待60秒(cluster-node-timeout)后,制定第二轮投票计划

76803:S 09 Jun 17:03:21.656 # Start of election delayed for 558 milliseconds (rank #0, offset 86).

12.从库2222 发起第二轮投票

76803:S 09 Jun 17:03:22.259 # Starting a failover election for epoch 45.

12.由于其余两个主库都已经把 主库2222 设为fail,所以这一轮投票 从库2222 可以拿到两票,从而执行切换成主库的操作

76803:S 09 Jun 17:03:22.260 # Failover election won: I'm the new master.
76803:S 09 Jun 17:03:22.260 # configEpoch set to 45 after successful failover

总结

造成需要两轮投票的原因是,从库先于其他主库拿够多数派的pfail,然后从库将自己维护的主库flags设置fail,但没有广播fail信息到其他节点。到下一次从库clusterCron检测到自己主库的flags为fail,则发起投票。而在其他存活主库收到从库投票请求时,由于clusterCron是0.1s发起一次,也就是说从库主库flags设为fail到下一次clusterCron,只间隔0.1s,再加上投票延迟的时间(小于1s),在此阶段,其他存活主库都还没有收够pfail来将挂掉主库的flags转为fail,所以拒绝投票。从库需要发起第二轮投票。
集群通信见:
Redis cluster gossip
集群从库自动failover机制见:
Redis cluster 从库自动failover机制

你可能感兴趣的:(Redis,redis,数据库)