假设初始的 Leader 服务器 Server1 在提出了⼀个事务Proposal3 之后就崩溃退出 了,从⽽导致集群中的其他服务器都没有收到这个事务Proposal3。于是,当 Server1 恢复过来再次加 ⼊到集群中的时候,ZAB 协议需要确保丢弃Proposal3这个事务。
综上所述,ZAB的选举出来的Leader必须满足以下条件:
能够确保提交已经被 Leader 提交的事务 Proposal,同时丢弃已经被跳过的事务 Proposal。即:
新选举出来的 Leader 不能包含未提交的 Proposal。
新选举的 Leader 节点中含有最大的 zxid 。
ZAB如何数据同步所有正常运行的服务器要么成为Leader,要么成为Follower并和Leader保持同步。
完成Leader选举(新的 Leader 具有最高的zxid)之后,在正式开始⼯作(接收客户端请求)之前,Leader服务器会⾸先确认事务⽇志中的所有Proposal是否都已经被集群中过半的机器提交了,即 是否完成数据同步 。
Leader服务器需要确保所有的Follower服务器能够接收到每⼀条事务Proposal,并且能够正确地将所有已经提交了的事务Proposal应⽤到内存数据中。等到 Follower服务器将所有其尚未同步的事务 Proposal 都从 Leader 服务器上同步过来并成功应⽤到本地数据库中后,Leader服务器就会将该Follower服务器加⼊到真正的可⽤Follower列表中,并开始之后的其他流程。
ZAB运行时状态ZAB协议设计中,每个进程都有可能处于如下三种状态之一:
LOOKING:Leader选举状态,正在寻找Leader
FOLLOWING:当前节点是Follower。与Leader服务器保持同步状态
LEADING:当前节点是Leader,作为主进程领导状态。
ZAB状态的切换启动时的状态转换
所有进程的初始状态都是LOOKING状态,此时不存在Leader。
接下来,进程会试图选举出来一个新的Leader,Leader切换为LEADING状态,其它进程发现已经选举出新的Leader,那么它就会切换到FOLLOWING状态,并开始与Leader保持同步。
处于FOLLOWING状态的进程称为Follower,LEADING状态的进程称为Leader。
当Leader崩溃或者放弃领导地位时,其余的Follower进程就会切换到LOOKING状态开始新一轮的Leader选举。
运行过程中的状态转换
一个Follower只能和一个Leader保持同步,Leader进程和所有的Follower进程之间通过心跳监测机制来感知彼此的情况。
若Leader能够在超时时间内正常的收到心跳检测,那么Follower就会一直与该Leader保持连接。
如果在指定时间内Leader无法从过半的Follower进程那里接收到心跳检测,或者TCP连接断开,那么Leader会放弃当前周期的领导,并转换为LOOKING状态;其他的Follower也会选择放弃这个Leader,同时转换为LOOKING状态,之后会进行新一轮的Leader选举
ZAB的四个阶段 选举阶段(Leader Election)节点在一开始都处于选举阶段,只要有一个节点超过半数阶段的票数,它就可以当选准Leader,只有到达第三个阶段(同步阶段),这个准Leader才会成为真正的Leader。
这一阶段的目的就是为了选出一个准Leader,然后进入下一阶段。
发现阶段在这个阶段中,Followers和上一轮选举出的准Leader进行通信,同步Followers最近接受的事务Proposal。这个阶段主要目的是发现当前大多数节点接受的最新提议,并且准Leader生成新的epoch,让Followers接受,更新它们的acceptedEpoch。
一个Follower只会连接一个Leader,如果有一个节点F认为另一个Follower P是Leader,F在尝试连接P时会被拒绝,F被拒绝后,就会进入选举阶段。
同步阶段同步阶段主要是利用 Leader 前一阶段获得的最新 Proposal 历史,同步集群中所有的副本。
只有当 quorum(超过半数的节点) 都同步完成,准 Leader 才会成为真正的 Leader。Follower 只会接收 zxid 比自己 lastZxid 大的 Proposal。
广播阶段到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 Leader 可以进行消息广播。同时,如果有新的节点加入,还需要对新节点进行同步。
需要注意的是,Zab 提交事务并不像 2PC 一样需要全部 Follower 都 Ack,只需要得到 quorum(超过半数的节点)的Ack 就可以。