zookeeper选举整个流程

基于zookeeper3.4.9

0.zk初始化

org.apache.zookeeper.server.quorum.QuorumPeerMain#initializeAndRun()方法,初始化操作,通信管理和参数加载等。

1.zookeeper选举

leader状态确认:

        选举出来的leader和followers需要经过,通信,确认有半数的followers通信ack之后,才确认了各自的状态。

        QuorumPeer.run(){}方法,进行状态判断,如果为LOOKING,则进行选举算法;


选举算法(红框中为选举算法的具体实现)

通过选举,得到leader节点==>currentVote,以及自己节点的选举状态;

具体投票如下:

 1.每个节点启动时,拿到自己的zxid,从历史数据中获取,默认值为0;实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

        logicalclock为选举轮数,在同一轮的选票,才有效;

        peerEpoch:每次leader选举完成之后,都会选举出一个新的peerEpoch,用来标记事务请求所属的轮次为节点历史选举为leader轮数,每参与一轮选举,leader的peerEpoch,在所有节点中取最大的peerEpoch+1;

        recvset:选举过程中,选票箱的概念,里面存放着所有选举者的选票

        outofelection:接受到的leader节点的选票;如果由于网络故障,当前leader挂断,新的选举产生,leader节点又恢复时,就会出现leader的选票了;

        选举开始,选举时钟+1;

选举开始时,初始化选举基本参数


获取其他节点广播的选票;


获取其他节点广播的选票;

选票解读:

选票解读

具体步骤:

                1.不在一个选举轮次,比当前节点的轮次大,清空当前节点的选票箱,同意n节点的票,广播给其他节点。

                2.比当前节点轮次小,忽略。

                3.totalOrderPredicate(),选票对比:

选票对比

                   1) peerEpoch对比,谁大选谁;

                    2)peerEpoch相等,谁的zxid大,或者zxid相等但节点id大,选谁。

                    3)如果n节点的选票更优,则更新自己的选票。

                4.将收到的选票放入选票箱。

  票数过半以后:

票数过半以后,确认节点状态,退出选举算法,做后续确认工作

1.确认选票箱中的选票,有节点票数过半,返回当前选票。(FastLeaderElection.termPredicate())

确定票数过半逻辑

2.recvqueue 中持续在获取其他节点的选票,设置的200ms超时,以防网络延时。在这个过程中,如果网络延时,节点B已经当选了Leader返回出来了,但是A在这个时候还没有退出,又接受到了D,E节点的选票,会继续选举,结果又选出了E节点为Leader,这时候,就出现了双leader的情况,下面就需要进行确认机制,排除其他leader,剩下一个leader节点。

Synchronization确认leader节点

自己的状态如果为leader,则调用leader.lead(),方法,做选举成功以后的事情

leader的主要逻辑

开启阻塞,等待follower的确认。

开启learnnerHandler,(LeaderHandler是follower和observer的主要通信逻辑类),ss监听开启,不断接收信息,有一个信息出来,就执行一个LearnHandler,

开启与follower的长连接

与follower节点通信,确认,然后followerCounter+1;


Leader的确认消息

Leader.lead()方法,会等待follower的确认,


等待确认,阻塞方法


等待确认具体路基

如果不是真正的leader节点,弹出异常,退出leader.lead()方法,当前节点退出,重新进入选举流程。

Follower.follower()方法,主要给leader发送消息确认,然后进入接受消息的状态。

源码下次再说吧。

你可能感兴趣的:(zookeeper选举整个流程)