Redis - Cluster - 源码总结(三)
集群中的节点总是在进行着 gossip 信息交换,一个发一个收,收发之间完成了信息的交换,业务动作的触发执行。
收与发对应着两块代码:定时任务和消息接收处理。
定时任务
集群中的节点每 100ms 的时间间隔定时执行既定任务,任务的主要内容如下:
handshake 超时处理
当前节点收到其他节点的 meet 消息时,只是将该节点信息加入到本节点维护的集群信息中并设置该节点处于 handshake 状态,并不会马上建立连接与其通信。
定时任务执行时,若发现本节点还未与集群中的某节点建立连接时,则会建立连接并发送 meet 或 ping 消息,若该节点回复 pong 消息后,则本节点认为完成了 handshake。
定时任务也同时会进行检测,如果本节点和某节点迟迟没有完成 handshake,则认为 handshake 超时,此时会将该节点从集群信息中移除,表示 handshake 失败,加入集群失败。
创建连接 &handshake
创建连接如上文所述,连接创建成功后,本节点会立即向目标节点发送 meet/ping 消息,开始 handshake。
随机 gossip
每隔 1s 执行一次,随机 5 次挑选 5 个节点,选出最久没有 gossip 交互的节点,向其发送 ping。
定向 gossip
作为随机 gossip 的重要补充,向超过 nodetimeout/2 时间没有 gossip 交互的所有节点发送 ping,以免节点信息太过于陈旧。
主观下线判断
本节点和目标节点通过 ping、pong 交互时间来进行判断,本节点发送 ping 后,如果 nodetimeout 时间还为收到 pong,则判断目标节点主观下线。
若判断为主观下线,只是将目标节点标志更新为主观下线,并不会立即通知其他节点,而是等到后续发送 ping 时,将目标节点主观下线信息发送出去(如果目标节点信息被选中要发出去)
设置主从同步
如果本节点是从节点,并且有指定的健康的主节点,则与主节点建立同步。
故障转移
如果本节点是从节点,且主节点已经客观下线,则本节点会发起故障转移流程。
【条件】
从节点要能够发起一次故障转移流程,要求是比较多的:
1、本节点是从节点 &有主节点且客观下线 &主节点有负责处理槽
2、本节点与主节点断线时间不超过 nodetimeout * 10
即本节点和主节点断线时间太长,本节点的数据则很有可能太过陈旧,此时本节点是没有资格去发起故障转移流程的
【执行过程】
1、定拉票时间
多个从节点都是有机会被选中来执行故障转移的,那么选哪个呢?肯定是想选择同步紧跟主节点的从节点,因为该从节点会有更完整的数据集。
redis 是执行的投票选举,所以复制偏移量越大,就会优先开始拉票环节,偏移量小一点,则推迟 1s 后再
开始拉票。先开始的,有更大的机会获得选票,则有更大的机会执行故障转移流程。
自增集群配置纪元
2、拉票
设置的拉票时间到达,从节点会自增集群配置纪元,作为本轮投票的标志,从节点会向所有节点拉票(只有负责处理槽的主节点的投票才有效),收到投票的节点,如果在本轮没有投票给其他节点,则投票给当前节点。
3、等待投票
如果累计收到的票数超过集群中主节点数量的一半,则开始真正执行故障转移。
如果等待超时,超过 notetimeout * 2 的时间仍然没有超过一半的票数,则再等待 nodetimeout *2 的时间,开始下一轮故障转移流程。
所以,一轮故障转移流程开始后,需要等待 nodetimeout * 4 的时间才能进行下一轮流程,留足了充足的时间给另外被选举出来的从节点执行故障转移
4、执行故障转移
1)取消被节点向故障主节点的同步,将本节点设置为主节点
2)将故障主节点的槽接收过来
3)向故障主节点的其他从节点发送消息,广播爷已经成为主节点了(其他从节点接收到后,将设置新的主节点并开始同步,自然也就不会再进行故障转移的尝试了)
评论