当前位置: 首页 > 后端技术 > Java

Zookeeper选举源码分析

时间:2023-04-01 23:30:42 Java

Leader选举,就是Election接口及其实现类 AuthFastLeaderElection。LeaderElection不推荐在3.4.0之后的版本使用。选举源码分析publicinterfaceElection{publicVotelookForLeader()throwsInterruptedException;publicvoidshutdown();}说明:  选举的父接口为Election,定义了两个方法,lookForLeader和shutdown,lookForLeader表示寻找aLeader,shutdown表示关闭,比如关闭服务器之间的连接。查看默认实现类FastLeaderElection:FastLeaderElection实现了Election接口,并重写了接口中定义的lookForLeader方法和shutdown方法。在源码分析之前,我们先介绍几个概念:外部投票:特指其他服务器发送的投票。内部投票:服务器自己的当前投票。Electionround:ZooKeeper服务器Leader选举的轮次,即逻辑时钟(logicalclock)。PK:指内部投票与外部投票进行比较,决定内部投票是否需要改变。选票管理sendqueue:选票发送队列,用于保存要发送的选票。recvqueue:投票接收队列,用于保存接收到的外部投票。lookForLeader函数当ZooKeeper服务器检测到当前服务器状态变为LOOKING时,会触发leader选举,即调用lookForLeader方法进行leader选举。publicVotelookForLeader()throwsInterruptedException{synchronized(this){//逻辑时钟会先递增,每次进行新的leader选举时,需要更新逻辑时钟logicalclock++;//更新投票(初始化投票)updateProposal(getInitId(),getInitLastLoggedZxid(),getPeerEpoch());}LOG.info("新选。我的id="+self.getId()+",proposedzxid=0x"+Long.toHexString(proposedZxid));//将您自己的投票(更新后的投票)发送到其他服务器sendNotifications();之后,每个服务器会不断从recvqueue队列中获取外部投票。如果服务器发现无法获得任何外部投票,它会立即确认是否与集群中的其他服务器保持有效连接。如果没有连接,则立即建立连接。当前的内部投票流程如下:/**如果没有收到足够多的通知??,则发送更多通知。*否则处理新的通知。*/if(n==null){//如果没有收到选票,勾选yes不是你的选票都已经投递了。如果您还没有交付,则表示您已与服务器断开连接。连接管理器.connectAll();}/**指数退避*/inttmpTimeOut=notTimeout*2;notTimeout=(tmpTimeOutcurrent,替换并发送消息//比较外部投票轮次和自己的轮次大小if(n.electionEpoch>logicalclock.get()){//外部大于内部,则将自己的轮次设置为外部投票logicalclock.set(n.electionEpoch);//清除你自己的投票recvset.clear();//比较投票if(totalOrderPredicate(n.leader,n.zxid,n.peerEpoch,getInitId(),getInitLastLoggedZxid(),getPeerEpoch())){updateProposal(n.leader,n.zxid,n.peerEpoch);}else{updateProposal(getInitId(),getInitLastLoggedZxid(),getPeerEpoch());}发送通知();}elseif(n.electionEpochcurId)))));}回到刚才的分支:}elseif(n.electionEpochvotes,Votevote){SyncedLearnerTrackervoteSet=newSyncedLearnerTracker();voteSet.addQuorumVerifier(self.getQuorumVerifier());如果(self.getLastSeenQuorumVerifier()!=null&&self.getLastSeenQuorumVerifier().getVersion()>self.getQuorumVerifier().getVersion()){voteSet.addQuorumVerifier(self.getLastSeenQuorumVerifier());}/**首先让视图保持一致。有时对等节点会根据时间对服务器有不同的*zxid。*///遍历投票集合for(Map.Entryentry:votes.entrySet()){//找到所有等于这个投票的记录if(vote.equals(entry.getValue())){voteSet.addAck(entry.getKey());}}//判断是否找到leader,即是否超过一半returnvoteSet.hasAllQuorums();}至此leader选举完成