Zookeeper之跟着zk学习怎么写阻塞至过半投票

  zookeeper中有很多逻辑是等到超过一半选票才能继续的场景。来看看怎么实现的吧

  Leader.getEpochToPropose

  在选出来主之后,会进入到这个分支

  QuorumPeer#

case LEADING:
                    LOG.info("LEADING");
                    try {
                        setLeader(makeLeader(logFactory));
                        leader.lead();
                        setLeader(null);
                    } catch (Exception e) {
                        LOG.warn("Unexpected exception", e);
                    } finally {
                        if (leader != null) {
                            leader.shutdown("Forcing shutdown");
                            setLeader(null);
                        }
                        updateServerState();
                    }
                    break;
                }

  同时,follower也会进入自己的follow分支,简单说下逻辑,就是和leader建立通信,然后发送消息,表示要和leader进行数据同步。

  消息类型为 Leader.FOLLOWERINFO

  这里忽略leader的网络通信部分逻辑。直接看获取epoch的逻辑。

  protected final Set<Long> connectingFollowers = new HashSet<Long>();

public long getEpochToPropose(long sid, long lastAcceptedEpoch) throws InterruptedException, IOException {
        synchronized (connectingFollowers) {
            if (!waitingForNewEpoch) {
                return epoch;
            }
            if (lastAcceptedEpoch >= epoch) {//找followe传过来的epoch最大值然后 +1
                epoch = lastAcceptedEpoch + 1;
            }
            if (isParticipant(sid)) {
                connectingFollowers.add(sid);
            }
            QuorumVerifier verifier = self.getQuorumVerifier();
            if (connectingFollowers.contains(self.getId()) && verifier.containsQuorum(connectingFollowers)) {//超过一半了
                waitingForNewEpoch = false;//这里改为false 下面的while就会跳出了
                self.setAcceptedEpoch(epoch);
                connectingFollowers.notifyAll();//唤醒阻塞
            } else {
                long start = Time.currentElapsedTime();
                if (sid == self.getId()) {
                    timeStartWaitForEpoch = start;
                }
                long cur = start;
                long end = start + self.getInitLimit() * self.getTickTime();
                while (waitingForNewEpoch && cur < end && !quitWaitForEpoch) {
                    connectingFollowers.wait(end - cur);
                    cur = Time.currentElapsedTime();
                }
                if (waitingForNewEpoch) {
                    throw new InterruptedException("Timeout while waiting for epoch from quorum");
                }
            }
            return epoch;
        }
    }

  QuorumVerifier 可以简单地理解就是比较是否大于集群服务器数量的一半的工具类

  

  向connectionFollowers中添加记录的逻辑在LearnerHandler

  不断地收到follower发过来的请求,慢慢的就满足了半数条件了

@Override
    public void run() {
        try {
            ......long newEpoch = learnerMaster.getEpochToPropose(this.getSid(), lastAcceptedEpoch);//不断向connectionFollowers中增加元素

 

posted on 2021-10-28 15:39  MaXianZhe  阅读(103)  评论(0编辑  收藏  举报

导航