手把手带你撸zookeeper源码-zookeeper启动(五)leader选举投票归档-确认当前zk服务的角色

接上文 手把手带你撸zookeeper源码-zookeeper启动(四)leader选举投票发送以及响应

 

本篇文章主要来看看当每个zk接收到其他服务器发送过来的投票之后,接下来会怎么处理

 //投票归档
                        recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));

                        if (termPredicate(recvset,
                                new Vote(proposedLeader, proposedZxid,
                                        logicalclock.get(), proposedEpoch))) {

                            // Verify if there is any change in the proposed leader
                            while((n = recvqueue.poll(finalizeWait,
                                    TimeUnit.MILLISECONDS)) != null){
                                if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,
                                        proposedLeader, proposedZxid, proposedEpoch)){
                                    recvqueue.put(n);
                                    break;
                                }
                            }

                            if (n == null) {
                                self.setPeerState((proposedLeader == self.getId()) ?
                                        ServerState.LEADING: learningState());

                                Vote endVote = new Vote(proposedLeader,
                                                        proposedZxid,
                                                        logicalclock.get(),
                                                        proposedEpoch);
                                leaveInstance(endVote);
                                return endVote;
                            }
                        }

recvset是一个HashMap集合,key为zk的sid, value: 就是投票对象Vote,里面包含了投票的数据,比如投票给谁作为leader,zxid等

再来看看termPredicate方法

protected boolean termPredicate(
            HashMap<Long, Vote> votes,
            Vote vote) {

        HashSet<Long> set = new HashSet<Long>();

        for (Map.Entry<Long,Vote> entry : votes.entrySet()) {
            if (vote.equals(entry.getValue())){
                set.add(entry.getKey());
            }
        }

        return self.getQuorumVerifier().containsQuorum(set);
    }

打个比方来说明更简单一些: 当前服务器是zk2,  然后 zk1向zk2发送投票数据,投票给zk3,此时这段的代码的意思就是遍历zk2服务器保存的所有投票数据,即votes。vote是zk1向zk2发送过来的投票数据,从votes集合中取出所有投了zk3的投票,把他们放入到set集合中

接下来看看containsQuorum()方法代码,进入的是QuorumMaj

public boolean containsQuorum(Set<Long> set){
        return (set.size() > half);
    }

很简单的代码,就是判断给zk3投的票数是不是超过了zk集群所有服务器总数的一半,如果是,则会把zk3作为leader,如果没有超过一半,则会接着继续投票

接下来就是判断是否还有其他zk发送过来的数据,如果有则继续处理

while((n = recvqueue.poll(finalizeWait,
                                    TimeUnit.MILLISECONDS)) != null){
                                if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,
                                        proposedLeader, proposedZxid, proposedEpoch)){
                                    recvqueue.put(n);
                                    break;
                                }
                            }

如果没有了,则会走下面的代码

if (n == null) {
                                self.setPeerState((proposedLeader == self.getId()) ?
                                        ServerState.LEADING: learningState());

                                Vote endVote = new Vote(proposedLeader,
                                                        proposedZxid,
                                                        logicalclock.get(),
                                                        proposedEpoch);
                                leaveInstance(endVote);
                                return endVote;
                            }

首先判断当前投递的leader的sid是否和本服务器myid一样,如果一样,则设置peerState为LEADING,作为leader,否则就设置状态为FOLLOWING或者OBSERVER,最后清空recvqueue, 返回有关leader的投票对象数据,leader整个选举结束

 

这篇文章就先写这么多,每次zk接受到其他的投票数据都会保存一下投票结果,然后对投票结果进行统计是否有sid的票数超过了集群总服务器数的一半,如果超过就可以确定leader,同时确定follower和observer

 

下篇文章来分析一下,当zk知道自己的角色之后,怎样按照自己的角色去做响应的事情

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值