【六】zookeeper 服务器选举与ZAB协议

本文为书籍《从Paxos到Zookeeper  分布式一致性原理与实践》倪超著_北京:电子工业出版社的读书笔记,这本书还是蛮值得推荐的。

一、服务器启动时期的Leader选举

假设Server1 (myId 1)这台启动了,它是无法进行Leader选举的,要等到Server2 (myId 2)启动后,这两台机器能够进行相互通信,每台机器试图找到一个Leader,于是进入Leader选举流程

1.每个Server会发出一个投票

由于是初始情况,因此对于Server1和Server2来说,都会将自己作为Leader服务器来进行投票。

每次投票包含的最基本的元素是:所推举的服务器的myid和ZXID。我们以(myid,ZXID)的形式来表示。

即Server1投票为(1,0),Server2投票为(2,0)。

然后各自将这个投票发给集群中其他所有机器。

2.接收来自各个服务器的投票

每个服务器都会接受来自其他服务器的投票。集群中的每个服务器在收到投票后,首先会判断该投票的有效性,包括检查是否是本轮投票,是否来自LOOKING状态的服务器。

3.处理投票

在接收到来自其他服务器的投票后,针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK的规则如下:

优先检查ZXID。ZXID比较大的服务器优先作为Leader。

如果ZXID相同的话,那么就比较myid。myid比较大的服务器作为Leader服务器。

现在我们来看server1和server2实际是如何进行投票处理的。对于server1来说,它自己的投票是(1,0),而收到的投票是(2,0)。首先会对比两者的ZXID,因为都是0,所以无法决定谁是Leader。接下来对比两者的myid,Server1收到的投票中myid是2,大于自己,于是会更新自己的投票为(2,0),然后重新发出去。

而对于server2来说,不需要更新自己的投票信息,只是再一次向集群中所有机器发出上一次投票信息即可。

4.统计投票

每次投票后,服务器都会统计所有投票,判断是否已有过半的机器接收到相同的投票信息。对于server1和server2服务器来说,都统计出集群中已经有两台机器接受了(2,0)这个投票信息。此时已过半。认为已经选举除了Leader为server2

5.改变服务器状态

一旦确定了Leader,每个服务器就会更新自己的状态:如果是Follower那么就变更为FOLLOWING,如果是Leader那么就变更为LEADING

二、服务器运行期间的Leader选举

在Zookeeper集群正常运行过程中,一旦选举出一个Leader那么所有服务器的集群角色一般不会发生变化。但是,如果Leader所在的服务器挂了,那么整个集群将暂时无法对外服务,并且进入新一轮的Leader选举。服务器运行期间的Leader选举和启动时期的Leader选举基本过程一致。

我们假设当前正在运行的Zookeeper服务器有3台机器组成,分别是Server1、Server2和Server3,当前Leader是Server2。假设在某一瞬间Leader挂了,这个时候便开始了Leader选举

1.变更状态

当Leader挂了之后,余下的非Observer服务器都会将自己的服务器状态变更为LOOKING,然后开始进入Leader选举流程。

2.每个Server会发出一个投票

在这个过程中,需要生成投票信息(myid,ZXID)。因为是运行期间,因此每个服务器上的ZXID可能不同,我们假定Server1的ZXID为123,而Server3的ZXID为122。在第一轮投票中,Server1和Server3都会投自己,即分别产生投票(1,123)和(3,122),然后各自将这个投票发给集群中所有机器。

3.接收来自各个服务器的投票

4.处理投票

对于投票的处理,和上面提到的服务器启动期间的处理规则是一致的。在这个例子里面,由于Server1的ZXID为123,Server3的ZXID为122,那么Server1会成为Leader

5.统计投票

6.改变服务器状态

三、ZAB协议

ZooKeeper使用的是ZAB协议作为数据一致性的算法, ZAB(ZooKeeper Atomic Broadcast ) 全称为:原子消息广播协议。

在Paxos算法基础上进行了扩展改造而来的,ZAB协议设计了支持原子广播崩溃恢复,ZAB协议保证Leader广播的变更序列被顺序的处理。

zookeeper根据ZAB协议建立了主备模型保证zookeeper集群中个副本之间数据一致性

ZAB协议中存在着三种状态,每个节点都属于以下三种中的一种:

Looking :系统刚启动时或者Leader崩溃后正处于选举状态

Following :Follower节点所处的状态,Follower与Leader处于数据同步阶段;

Leading :Leader所处状态,当前集群中有一个Leader为主进程;

协议核心

所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而余下的其他服务器称为Follower服务器。

Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提议),并将该Proposal分发给集群中所有的Follower服务器。

之后Leader服务器需要等待所有的Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向所有的Follower服务器分发Commit消息,要求其将前一个Proposal进提交。

协议阶段

ZAB协议整体可划分为两个基本的模式:消息广播和崩溃恢复

按协议原理可细分为四个阶段:选举(Leader Election)、发现(Discovery)、同步(Synchronization)和广播(Broadcast)

按协议实现分为三个时期:选举(Fast Leader Election)、恢复(Recovery Phase)和广播(Broadcast Phase)

ZAB选举(election)时当Follower存在ZXID(事务ID)时判断所有Follower节点的事务日志,只有lastZXID的节点才有资格成为Leader,这种情况下选举出来的Leader总有最新的事务日志,

基于这个原因所以ZooKeeper实现的时候把 发现(discovery)与同步(sync)合并为恢复(recovery) 阶段;

Election :在Looking状态中选举出Leader节点,Leader的lastZXID总是最新的;

Discovery :Follower节点向准Leader推送FOllOWERINFO,该信息中包含了上一周期的epoch,接受准Leader的NEWLEADER指令,检查newEpoch有效性,准Leader要确保Follower的epoch与ZXID小于或等于自身的;

sync :将Follower与Leader的数据进行同步,由Leader发起同步指令,最总保持集群数据的一致性;

Broadcast :Leader广播Proposal与Commit,Follower接受Proposal与Commit;

Recovery :在Election阶段选举出Leader后本阶段主要工作就是进行数据的同步,使Leader具有highestZXID,集群保持数据的一致性;

消息广播模式

1.在zookeeper集群中数据副本的传递策略就是采用消息广播模式。zookeeper中数据副本的同步方式与二阶段提交相似但是却又不同。二阶段提交的要求协调者必须等到所有的参与者全部反馈ACK确认消息后,再发送commit消息。要求所有的参与者要么全部成功要么全部失败。二阶段提交会产生严重阻塞问题。

2.ZAB协议中Leader等待follower的ACK反馈是指”只要半数以上的follower成功反馈即可,不需要收到全部follower反馈”

3.leader服务器与每个follower之间都有一个单独的队列进行收发消息,使用队列消息可以做到异步解耦。leader和follower之间只要往队列中发送了消息即可。

4.在广播事务Proposal之前,Leader服务器会首先为这个事务Proposal分配一个全局单调递增的唯一ID,我们称之为事务ID(即ZXID)。由于ZAB协议需要保证每一个消息严格的因果关系,因此必须将每一个事务Proposal按照其ZXID的先后顺序进行排序和处理。

5.zxid ——  最新事务ID

高32位是Leader的epoch,从1开始,每次选出新的Leader,epoch加一;

低32位为该epoch内的序号,每次epoch变化,都将低32位的序号重置;

保证了zkid的全局递增性

6.在这种简化的二阶段提交模型下,无法处理Leader服务器崩溃退出而带来的数据不一致问题,因此ZAB协议添加了崩溃恢复模式来解决这个问题

崩溃恢复模式

1.zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是leader服务器接受写请求,即使是follower服务器接受到客户端的请求,也会转发到leader服务器进行处理。

2.如果leader服务器发生崩溃,则zab协议要求zookeeper集群进行崩溃恢复和leader服务器选举。

3.ZAB协议崩溃恢复要求满足如下2个要求:

1. 确保已经被leader提交的proposal必须最终被所有的follower服务器提交。

2. 确保丢弃已经被leader出的但是没有被提交的proposal。

4.根据上述要求,新选举出来的leader不能包含未提交的proposal,即新选举的leader必须都是已经提交了的proposal的follower服务器节点。同时,新选举的leader节点中含有最高的ZXID。这样做的好处就是可以避免了leader服务器检查proposal的提交和丢弃工作。

数据同步

1.在zookeeper集群中新的leader选举成功之后,leader会将自身的提交的最大proposal的事物ZXID发送给其他的follower节点。follower节点会根据leader的消息进行回退或者是数据同步操作。最终目的要保证集群中所有节点的数据副本保持一致。

2.数据同步完之后,zookeeper集群如何保证新选举的leader分配的ZXID是全局唯一呢?

这个跟ZXID的设计相关:

ZXID是一个长度64位的数字,其中低32位是按照数字递增,即每次客户端发起一个proposal,低32位的数字简单加1。

高32位是leader周期的epoch编号,每当选举出一个新的leader时,新的leader就从本地事物日志中取出ZXID,然后解析出高32位的epoch编号,进行加1,再将低32位的全部设置为0。

这样就保证了每次新选举的leader后,保证了ZXID的唯一性而且是保证递增的。

Zab与Paxos

1.Paxos算法的确是不关心请求之间的逻辑顺序,而只考虑数据之间的全序,但很少有人直接使用paxos算法,都会经过一定的简化、优化。

2.Paxos算法在出现竞争的情况下,其收敛速度很慢,甚至可能出现活锁的情况,例如当有三个及三个以上的proposer在发送prepare请求后,很难有一个proposer收到半数以上的回复而不断地执行第一阶段的协议。因此,为了避免竞争,加快收敛的速度,在算法中引入了一个Leader这个角色,在正常情况下同时应该最多只能有一个参与者扮演Leader角色,而其它的参与者则扮演Acceptor的角色。
在这种优化算法中,只有Leader可以提出议案,从而避免了竞争使得算法能够快速地收敛而趋于一致;而为了保证Leader的健壮性,又引入了Leader选举,再考虑到同步的阶段,渐渐的你会发现对Paxos算法的简化和优化已经和上面介绍的ZAB协议很相似了。

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页