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了,那么其他主库会投票,(当然这里也要有大多数的主节点凑够下线报告链表才行)。
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机制