持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
Zookeeper核心启动源码流程描述(三)
QuorumPeer.run()开启器集群启动线程
LOG.debug("Starting quorum peer");
主流程大概描述:
-
while 死循环 获取当前节点的状态(looking,OBSERVING,FOLLOWER,LEADER)四种状态
-
case looking
源码的注释解释是每当节点状态变成LOOKING的时候,调用lookForLeader()方法,开始新的一轮选举,向所有其他节点发送选票通知,接下来是具体的流程;
-
首先会把当前节点的选举周期➕1
-
初始化选票 把leader投给自己;
-
sendNotifications向及群中其他节点发送选自己选票的信息,把选票通知封装成ToSend发送到队列LinkedBlockingQueue sendqueue;
-
接下来有是循环节点之间交换选票数据,直至选出leader
循环条件:当前节点是LOOKING,并且还未选出leader
-
从LinkedBlockingQueue recvqueue队列中获取选票做leader选举:选票Notification n
-
如果队列中选票不存在,则跟集群中其节点建立连接
-
存在则判断发送当前选票的机器的选举状态
LOOKING:
第一步先判断 接收到选票的选举周期如果大于当前机器的选举周期,那么把自己的选举周期更新成最新的,清空当前选票结果集合,接下来做一次选举判断:
大致的逻辑判断 是,接收到选票跟当前认为的选票做比较,如果接收到的胜利,则把选票信息更新成接收到的选票,发送出去;否则更新成自己发送出去),给集群中所有其他参与投票的节点发送选票;
return ((newEpoch > curEpoch) || ((newEpoch == curEpoch) && ((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId)))));把接收到的选票存进选票箱recvset recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch))
循环遍历选票箱 recvset ,跟本机认为的leader选票做筛选。如果相等则将投票机器的sid加入SyncedLearnerTracker voteSet = new SyncedLearnerTracker();
然后判断return (ackSet.size() > half); 投票机器是否超过半数;为true的话,
再从recvqueue队列里面获取选票信息,如果可以取到选票数据,则证明集群中有新的机器加入进来,因此需要重新跟本节点选出来的leader选票重新PK,如果新进入的选票获胜则再重新放入recvqueue队列,重新循环选举一次;
如果n==null,则判断
self.setPeerState((proposedLeader == self.getId()) ? ServerState.LEADING: learningState())
表达式意思是如果本机投票的sid是自己的机器id,则自己就是leader,否则就是FOLLOWER;
case FOLLOWING: case LEADING:逻辑跟上述判断差不多,大致就是判断当前节点状态角色的判断;
-