赞
踩
ZAB 协议,全称 Zookeeper Atomic Broadcast(Zookeeper 原子广播协议),是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的一致性协议。基于该协议,ZooKeeper 实现了一种主从模式的系统架构来保持集群中各个副本之间的数据一致性。当 Zookeeper 集群中的一台服务器出现以下两种情况之一时,需要进入 Leader 选举:(1)服务器初始化启动;(2)服务器运行期间 Leader 故障。
~
本篇内容包括:关于 ZAB 协议、Zookeeper 选主时机、Zookeeper 选主机制。
ZAB 协议,全称 Zookeeper Atomic Broadcast(Zookeeper 原子广播协议),是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的一致性协议。基于该协议,ZooKeeper 实现了一种主从模式的系统架构来保持集群中各个副本之间的数据一致性。
作为分布式共识算法的一员,Zab 算法构成了著名的 ZooKeeper 的基石。与赫赫有名的 Paxos、Raft 一样,Zab 算法也提供了强一致性的保证。
从设计上看,ZAB 协议和 Raft 很类似。ZooKeeper 集群中,只有一个 Leader 节点,其余均为 Follower 节点。
Zookeeper 集群中的机器分为以下三种角色:
ZooKeeper 服务器有四种工作状态:
LOOKING:竞选状态,寻找 Leader。当服务器处于该状态时,它会认为当前服务器没有 Leader,因此需要进入 Leader 选举状态。
FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。
LEADING:领导者状态。表明当前服务器角色是 Leader。
OBSERVING:观察者状态。表明当前服务器角色是 Observer。
当 Zookeeper 集群中的一台服务器出现以下两种情况之一时,需要进入 Leader 选举:(1)服务器初始化启动;(2)服务器运行期间 Leader 故障。
FOLLOWING 状态节点(Follower)的主流程:
void followLeader() throws InterruptedException {
try {
......
while (this.isRunning()) {
readPacket(qp);
processPacket(qp);
}
// 如果上面的 while 循环内出现异常
// Ps:长时间没有收到 Leader 的消息也是异常
} catch (Exception e) {
// 出现异常就退出了 while 循环
// 也就结束了 Follower 的处理流程
}
LOOKING 状态节点的主流程:
public void run() {
while (running) {
switch (getPeerState()) {
case FOLLOWING:
try {
setFollower(makeFollower(logFactory));
follower.followLeader();
} catch (Exception e) {
......
} finally {
follower.shutdown();
setFollower(null);
// 状态更新为 LOOKING
updateServerState();
}
break;
......
}
}
在 Leader 节点的主循环流程中,会判断多数派节点的消息状态,如下:
void lead() throws IOException, InterruptedException {
......
while (true) {
......
// 判断每个每个 Follower 节点的状态
// 是否与 Leader 保持同步
for (LearnerHandler f : getLearners()) {
if (f.synced()) {
syncedAckSet.addAck(f.getSid());
}
}
......
}
if (!tickSkip && !syncedAckSet.hasAllQuorums()) {
// 如果失去了大多数 Follower 节点的认可,就跳出 Leader 主循环,进入选主流程
break;
}
......
}
// LearnerHandler::synced() 逻辑
// 即判断当前是否已经过了期望得到的 Follower 的下一个消息的期限:tickOfNextAckDeadline
public boolean synced() {
return isAlive() && leader.self.tick.get() <= tickOfNextAckDeadline;
}
# Server id(myid 或 sid):服务器 ID
比如有三台服务器,编号分别是 1,2,3。编号越大在选择算法中的权重越大,比如初始化启动时就是根据服务器 ID 进行比较。
# Zxid:事务ID
服务器中存放的数据的事务 ID,值越大说明数据越新,在选举算法中数据越新权重越大。
zxid 有两部分组成:高 32位 是 epoch,低 32位 是 epoch 内的自增 id,由 0 开始。每次选出新的 Leader,epoch 会递增,同时 zxid 的低 32 位清 0
# Epoch:逻辑时钟
也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的,每投完一次票这个数据就会增加。
选举大致流程:
假设我们有服务器 1~5,服务器初始化启动选主流程(粗略版):
Zookeeper 集群运行期间无法和 Leader 保持正常连接时,即如果 Leader 挂了,或者 Leader 服务器故障都会进行新一轮的 Leader 选举。需要重新选举时,选举过程就需要加入数据 id,服务器id,和逻辑时钟。
集群重新选举时,根据 myid 和 zxid 的大小共同决断,zxid 更大的优先成为 Leader,选举的标准(粗略版):
总结:Zookeeper 集群按 myid 从小到大依次启动初始化时,在超过半数机器的投票的情况下,谁的 myid 最后,谁就是 Leader,知道这个定律,不同的集群规模我们都可以推算出谁是 Leader。
# 集群初始化时:
集群重新选举时,根据 myid 和 zxid 的大小共同决断,zxid 更大的优先成为 Leader。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。