ZAB协议(ZooKeeper原子消息广播协议)
只针对ZooKeeper的崩溃可恢复的原子消息广播协议。
ZooKeeper使用一个单一的主进程来接收并处理客户端的事务处理,并采用ZAB协议,将服务器数据的状态变更以事务Proposal的形式广播道所有的副本进程上去。ZAB协议的这个主备模型架构保证了同一时刻集群中只能够有一个主进程来广播服务器的状态变更。ZAB能够保证一个全局的变更序列被应用。ZAB协议还要保证,当主进程出现崩溃或重启时,能够继续工作。
核心
所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而余下的其他服务器则成为Follower服务器。Leader服务器负责将一个客户端事务请求转换成一个事务Proposal,并将该Proposal发送给集群中所有的Follower,当有超过半数的Follower进行了正确反馈之后,那么Leader会再发送一个commit,要求其将前一个Proposal进行提交。
协议介绍
ZAB协议有崩溃恢复和消息广播。
-
消息广播:类似于2PC,但是移除了中断逻辑,即所有的Follower服务器要么正常反馈,要么就抛弃Leader。Leader在收到超过半数的Follower的反馈后,就会命令事务提交ZooKeeper需要保证每个事物操作的顺序性,所以每个事务Proposal都会有一个全局单调递增的ZXID,通过将Proposal放入到每个Follower的单独队列中,确保顺序。
-
崩溃恢复:LEADER崩溃后,ZAB需要保证在非Leader已提交事务proposal最终被所有服务器都提交,只在Leader提交的事务被舍弃。以最大ZXID为Leader的原因:新选出来的leader具有全部提案。Leader可以省去检查Proposal的提交和丢弃工作这一步;数据同步即新Leader会为每个Follower准备一个队列,然后一个Proposal,一个Commit这样的顺序发送给Follower。ZXID的结构是高32位是epoch周期(即第几次选举Leader了),低32位是根据提案累加的。基于这样一个策略,当一个包含上一个周期未提交的事务Proposal的服务器启动时,它肯定无法成为Leader,因为epoch在高32位。这样子,follower的zxid超前时,也会根据leader的proposal zxid进行回退。
深入ZAB协议
-
阶段一:发现,Follower将自己的epoch值发送给准Leader,准Leader会选择出最大的epoch值,并加1,标记为e‘。准Leader将e’发送给Follower,Follower将自己的opoch值设置为e’,同时向这个Leader返回Ack消息,这个ACK消息包含了当前的epoch值以及历史事务Proposal集合h。准Leader会从中选择ZXID最大的事务集合,作为初始化事务集合Ie’。
-
阶段二:同步,Leader以NEWLEADER(e’, Ie’)消息的形式发送给所有Quorum中的Follower。当Follower接收到来自Leader L的NEWLEADER(e’,Ie’)后,会执行事务应用应用,并反馈给Leader。当Leader收到超过半数的Follower的反馈,就会向所有的Follower发送Commit消息。当Follower收到来自Leader的Commit消息后,会以此处理并提交所有在Ie’中未处理的事务。至此阶段二完成。
-
阶段三:广播,Leader 接收到客户端新的事务请求后,会生成对应的事务Proposal,并向所有的Follower发送。Follower处理事务,并反馈给Leader。当Leader有超过半数的正确响应之后,就会向所有的Follower发送Commit。Follower接收到之后,就会开始Commit。
运行状态分析
在ZAB的设计中,每个进程可能都处于以下状态之一: LOKING,FOLLOWING,LEADING。所有进程启动的时候,都处于LOOKING状态。如果选举出新的Leader了,那么非Leader就会马上切换为Following状态,并开始与Leader保持同步,Leader则会进入LEADING状态。当Leader挂掉或放弃领导地位时,其余Follower就会转为LOOKING状态,并开始进行新一轮Leader选举。因此,在ZAB协议运行过程中,每个进程在LEADING,FOLLOWING和LOOKING状态之间不断地转换。在原子广播阶段,leader会为每个Follower单独搞一个队列进行事务Proposal发送,如果超过半数的Follower和leader失联,那么leader会进去LOOKING状态,也就是前面所说的放弃领导地位。