苏州网站建设排名,做网站怎么放视频,org已经备案的网站,今天31个省新增最新消息ZAB协议
ZooKeeper是如何选举领导者的。
首先我们来看看ZooKeeper是如何实现成员身份的#xff1f; 在ZooKeeper中#xff0c;成员状态是在QuorumPeer.java中实现的#xff0c;为枚举型变量
public enum ServerState {
LOOKING,
FOLLOWING,
LEADING,
OBSERVING
}其实 在ZooKeeper中成员状态是在QuorumPeer.java中实现的为枚举型变量
public enum ServerState {
LOOKING,
FOLLOWING,
LEADING,
OBSERVING
}其实ZooKeeper没有直接定义成员身份而是用了对应的成员状态来表示比如处于FOLLOWING状态的节点为跟随者。如果你想研究相关成员的功能和实现那么可以把对应的成员状态作为切入点来研究。比如你想研究领导者的功能实现可以在代码中搜索LEADING关键字然后研究相应的上下文逻辑进而得到自己想要的答案。 如果跟随者将自己的状态从跟随者状态变更为选举状态就表示跟随者在发起领导者选举那么在ZooKeeper中领导者选举是如何实现的呢 领导者选举是在FastLeaderElection.lookForLeader()中实现的。其核心实现流程如图所示。
为了更好地理解这个流程我们来一起走读下核心代码:
1.在集群稳定运行时处于跟随者状态的节点会调用Follower.followLeader()函数周期性地读数据包和处理数据包如代码所示
QuorumPacket qp new QuorumPacket();
while (this.isRunning()) {
//读取数据包
readPacket(qp);
// 处理数据包
processPacket(qp);
}2.当跟随者检测到连接到领导者的读操作超时时(比如领导者节点故障了)它会抛出异常(Exception)跳出上面的读取数据保和处理数据保的循环并将节点状态变更为选举状态。如代码所示
public void run() {
case FOLLOWING:
......
finally {
// 关闭跟随者节点
follower.shutdown();
setFollower(null);
// 设置状态为选举状态
updateServerState();
}
break;
......
}3.当节点处于选举状态时它将调用makeLEStrategy().lookForLeader()函数(实际对应的函数为FastLeaderElection.lookForLeader())发起领导者选举如代码所示
setCurrentVote(makeLEStrategy().lookForLeader());4.在FastLeaderElection.lookForLeader()函数中节点需要对逻辑时钟(也就是选举的轮次)的值执行加1操作表示开启一轮新的领导者选举然后创建投票提案(默认推荐自己为领导者)并通知所有节点如代码所示
synchronized(this) {
// 对逻辑时钟的值执行加一操作
logicalclock.incrementAndGet();
// 创建投票提案并默认推荐自己为领导者
updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());
}
// 广播投票信息给所有节点
sendNotifications();5.当节点处于选举状态时它会周期性地从队列中读取接收到地投票信息直到选举成功如代码所示
while((self.getPeerState() ServerState.LOOKING) (!stop)) {
// 从队列中读取接收到地投票信息
Notification n recvqueue.poll(notTimeout, TimeUnit.MILLISECONDS);
......
}6.当接收到新的投票信息时节点会进行领导者PK来判断谁更适合当领导者。如果投票信息中提议的节点比自己提议的节点更适合作为领导者 则该节点会更新投票信息推荐投票信息中提议的节点作为领导者并广播给所有节点如代码所示
else if (totalOrderPredicate(n.leader, n.zxid,n.peerEpoch,proposedLeader, proposedZxid, proposedEpoch)) {
// 如果投票信息中提议的节点比自己提议的节点更适合作为领导者则更新投票信息
// 并推荐投票信息中提议的节点
updateProposal(n.leader,n.zxid,n.peerEpoch);
// 将新的投票信息广播给所有节点
sendNotifications();
}7.如果自己提议的领导者赢得大多数选票则执行步骤8变更节点状态退出选举如果自己提议的领导者仍未赢得大多数选票则执行步骤5继续从接收队列中读取新的投票信息。8.最后当节点提议的领导者赢得大多数选票时则节点会根据投票结果判断并变更节点状态(如变更为领导者或跟随者)然后退出选举,如代码所示
if (voteSet.hasAllQuorums()) {
......
// 根据投票结果判断并设置节点状态
setPeerState(propsedLeader, voteSet);
// 退出领导者选举
Vote endVote new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch);
leaveInstance(endVote);
return endVote;
......
}注意
这里只是演示了一种选举情况还有更多情况需要实践比如接收到来自逻辑时钟的值比当前节点的值小的节点的投票哦信息再比如接收到来自领导者的投票信息
如何从故障中恢复
在前面我们提到了ZAB协议的领导者选举在我看来它只是选举了一个适合当领导者的节点然后把这个节点的状态设置成LEAEDING状态。此时这个节点还不能作为主节点处理写请求也不能使用领导职能(比如它没办法阻止其他领导者广播提案)。也就是说集群还没有从故障中恢复过来而成员发现和数据同步会解决这个问题。 总的来说成员发现和数据不同不仅让新领导者正式成为领导者确立了它的领导关系还解决了个副本数据冲突的问题实现了数据副本的一致性使集群能够正常处理写请求这里需要注意的是
1.确立领导关系是指在成员发现(DISCOVERY)阶段领导者和大多数跟随者建立连接并再次确认各节点对自己当选领导者没有异议从而确立自己的领导关系2.处理冲突数据是指在数据同步(SYNCHRONIZATION)阶段领导者以自己的数据为准解决各节点数据副本不一致的问题。 理解这两点有助于更好地理解ZooKeeper如何恢复故障以及当主节点崩溃时哪些数据会丢失、哪些数据不会丢失的原因等。换句话说通过上述内容我们能更好地理解ZooKeeper的节点故障容错能力