Redis 集群故障转移
故障判定
集群中的所有节点,都会周期性的使用心跳包进行通信。
- 节点 A 给节点 B 发送 ping 包,B 就会给 A 返回 pong 包,这两个包中包含了集群的配置信息
- 每个节点,每秒钟,都会给一些随机的节点发送 ping 包,而不是全发一遍,避免当节点过多时,消耗了太多的网络资源
- 当 B 没有按时给 A 发送 pong 包,A 就会尝试重置 B 的 TCP 连接,若不能连接成功,A 就会把 B 设置为 PFAIL 状态(相当于主观下线)
- A 将 B 判定为 PFAIL 状态后,会通过 Redis 内置的 Gossip 协议,和其他的节点进行沟通,判断 B 是否下线。(每个节点都会维护自己的 “下线列表”,每个节点的 “下线列表都不相同”)
- 若集群中有半数的节点都判定 B 为 PFAIL 撞状态,那么 A 就会将 B 判定为 FAIL(客观下线),并把这个消息告诉其他节点,这样其他节点就会将 B 判定为 FAIL 状态
经过上述流程后,B 就会被判定为故障节点。
故障迁移
- 若 B 是从节点,就不需要进行故障转移
- 若 B 是主节点,就会由 B 的从节点(如 C 和 D)进行故障迁移
故障迁移,就会将一个分片中的从节点升级为主节点(Raft 算法),继续为集群提供服务。
- 从节点会判断自己是否有竞选资格,若从节点与主节点太久没有进行通信,就表示从节点已经很久没有从主节点那里同步数据,即从节点与主节点的数据差异较大,就会失去竞选资格
- 若 C 和 D 都具有竞选资格,那么这两个节点就会休眠一段时间(休眠时间 = 500ms 基础时间 + [0, 500ms] 随机时间 + 排名*1000m),offset 越大,排名越小。那么休眠时间很大程度上与 offset 有关,即节点同步的数据越多,大概率就会率先醒来
- 若 C 节点先醒来,就会给集群中的其他节点,进行拉票,但是只有主节点才能进行投票
- 当 C 节点收到的票数超过集群中主节点数目的一半,就会晋升为主节点,自己执行 slave of no one 指令,并让 D 执行 slave of 指令
- C 节点会将自己晋升为主节点的消息,同步给集群中的其他节点,其余节点就会更新并保存新的集群结构
与哨兵模式不同的是,这里直接选举出了一个新的主节点,而哨兵模式是先选举出一个 leader,再由这个 leader 决定将谁晋升为主节点。
集群宕机
出现下面三种情况,会出现集群宕机:
- 某个分片中,所有主节点与从节点都宕机了
- 某个分片中,主节点宕机,但是从节点没有宕机
- 超过半数的主节点都宕机