zookeeper选举(二)-lookForLeader
/** * FastLeaderElection.lookForLeader * 选举核心方法 */ public Vote lookForLeader() throws InterruptedException { try { // 收票箱(节点状态是LOOKING发来的投票信息) HashMap<Long, Vote> recvVoteSet = new HashMap<>(); // 收票箱(选举结束节点发来的投票信息) HashMap<Long, Vote> outOfElection = new HashMap<>(); synchronized (this) { // 当前节点选举轮次 logicalClock.incrementAndGet(); // 初始化投票参数 updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch()); } // 群发Vote sendNotifications(); // LOOKING & not stop while ((self.getPeerState() == ServerState.LOOKING) && (!stop)) { Notification n = recvQueue.poll(200, TimeUnit.MILLISECONDS); if (n == null) { if (manager.haveDelivered()) { sendNotifications(); } else { manager.connectAll(); } } else if (validVoter(n.sid) && validVoter(n.leader)) { switch (n.state) { // 对方选举状态(LOOKING) case LOOKING: // 如果对方选举轮次大于本节点选举轮次,投票箱直接清空,并更新本节点的投票轮次 if (n.electionEpoch > logicalClock.get()) { logicalClock.set(n.electionEpoch); recvVoteSet.clear(); // 如果对方发来的选举信息获胜 if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, getInitId(), getInitLastLoggedZxid(), getPeerEpoch())) { // 更新选举信息 updateProposal(n.leader, n.zxid, n.peerEpoch); } else { updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch()); } sendNotifications(); // 如果对方选举轮次小于本节点选举轮次 } else if (n.electionEpoch < logicalClock.get()) { // 直接忽略(不加入投票箱),WorkerReceiver里直接做了处理 break; // 如果处于同一选举轮次(这种情况比较多) } else if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) { // 如果对方投票信息获胜,更新选举信息,并群发 updateProposal(n.leader, n.zxid, n.peerEpoch); sendNotifications(); } // 投票箱存入接收到的投票信息 recvVoteSet.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch)); // 接收到的当前投票信息(统计过半) if (termPredicate(recvVoteSet, new Vote(proposedLeader, proposedZxid, logicalClock.get(), proposedEpoch))) { // Verify if there is any change in the proposed leader while ((n = recvQueue.poll(200, TimeUnit.MILLISECONDS)) != null) { if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) { recvQueue.put(n); break; } } // 如果选票过半,且200ms内没新选票来,则选举初步结束 if (n == null) { self.setPeerState((proposedLeader == self.getId()) ? ServerState.LEADING : learningState()); Vote endVote = new Vote(proposedLeader, proposedZxid, logicalClock.get(), proposedEpoch); leaveInstance(endVote); return endVote; } } break; case OBSERVING: break; case FOLLOWING: case LEADING: // 当前节点和对方处于同一选举轮次 if (n.electionEpoch == logicalClock.get()) { recvVoteSet.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch)); if (ooePredicate(recvVoteSet, outOfElection, n)) { self.setPeerState((n.leader == self.getId()) ? ServerState.LEADING : learningState()); Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch); leaveInstance(endVote); return endVote; } } outOfElection.put(n.sid, new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state)); if (ooePredicate(outOfElection, outOfElection, n)) { synchronized (this) { logicalClock.set(n.electionEpoch); self.setPeerState((n.leader == self.getId()) ? ServerState.LEADING : learningState()); } Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch); leaveInstance(endVote); return endVote; } break; default: LOG.warn("Notification state unrecognized: {} (n.state), {} (n.sid)", n.state, n.sid); break; } } else { if (!validVoter(n.leader)) { LOG.warn("Ignoring notification for non-cluster member sid {} from sid {}", n.leader, n.sid); } if (!validVoter(n.sid)) { LOG.warn("Ignoring notification for sid {} from non-quorum member sid {}", n.leader, n.sid); } } } return null; } finally { try { if (self.jmxLeaderElectionBean != null) { MBeanRegistry.getInstance().unregister(self.jmxLeaderElectionBean); } } catch (Exception e) { LOG.warn("Failed to unregister with JMX", e); } self.jmxLeaderElectionBean = null; LOG.debug("Number of connection processing threads: {}", manager.getConnectionThreadCount()); } }
private boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch) { if (self.getQuorumVerifier().getWeight(newId) == 0) { return false; } return ((newEpoch > curEpoch) || ((newEpoch == curEpoch) && ((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId))))); }
/** * 判断该投票是否过半 */ private boolean termPredicate(HashMap<Long, Vote> votes, Vote vote) { HashSet<Long> set = new HashSet<>(); for (Map.Entry<Long, Vote> entry : votes.entrySet()) { if (vote.equals(entry.getValue())) { set.add(entry.getKey()); } } return self.getQuorumVerifier().containsQuorum(set); } @Override public boolean equals(Object o) { if (!(o instanceof Vote)) { return false; } Vote other = (Vote) o; if ((state == ServerState.LOOKING) || (other.state == ServerState.LOOKING)) { return (id == other.id && zxid == other.zxid && electionEpoch == other.electionEpoch && peerEpoch == other.peerEpoch); } else { if ((version > 0x0) ^ (other.version > 0x0)) { return id == other.id; } else { return (id == other.id && peerEpoch == other.peerEpoch); } } }
private boolean ooePredicate(HashMap<Long, Vote> recv, HashMap<Long, Vote> ooe, Notification n) { return (termPredicate(recv, new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state)) && checkLeader(ooe, n.leader, n.electionEpoch)); } private boolean checkLeader(HashMap<Long, Vote> ooe, long leader, long electionEpoch) { boolean predicate = true; if (leader != self.getId()) { if (ooe.get(leader) == null) { predicate = false; } else if (ooe.get(leader).getState() != ServerState.LEADING) { predicate = false; } } else if (logicalClock.get() != electionEpoch) { predicate = false; } return predicate; }
posted on 2020-09-30 16:09 www_practice 阅读(182) 评论(0) 编辑 收藏 举报