Zookeeper的ZAB协议

ZAB(Zookeeper Atomic Broadcast) zookeeper原子消息广播协议。 ZAB是专门为zk而设计的一种支持奔溃可恢复的原子广播协议

Zk使用一种主备模式的系统架构来保持集群中各副本数据的一致性。具体是通过,1个单一的主进程处理所有的写请求,并采用zab原子广播协议,将数据变更通过事务Proposal形式推送到副本进程。

分布式事务中需要保证顺序执行的状态变更有先后顺序,即当前事务之前的其他事务必须在当前事务执行之前被执行。这就要求ZAB协议能够保证一个全局变更序列被顺序应用,说的简单点就是串行执行。 

ZAB协议的核心

所有的事务请求(写请求)必须由全局唯一的服务器来协调处理,这台服务器被称为Leader服务器。余下的服务器被称为Follower。ZAB协议定义:在集群处理事务请求(写请求)时,Leader服务将客户端的请求转化为一个事务Proposal(提议),并负责分发给所有的follower,一旦超过半数的follower正确反馈以后,那么leader再次发送一个commit消息,要求follow将前一次Proposal进行提交。 

ZAB协议内容

消息广播

消息广播过程使用原子广播协议,类似二阶段提交。即 proposal -> commit 区别于二阶段提交的是,ZAB移除了中断逻辑,意味着leader可以在半数follower反馈Ack之后就开始commit事务。而不需要等待集群中所有的follower都反馈相应。但是这种简化的二阶段提交无法处理Leader崩溃退出的场景而导致数据不一致的问题,因此ZAB协议添加了另一个模式,崩溃恢复。另外消息广播基于tcp协议,因此能保证消息的顺序性。

事务ID(ZXID) 由于ZAB需要保证每个消息严格的因果关系,协议会为每一个事务分配一个全局单调递增的唯一ID.

崩溃恢复

崩溃恢复针对的是异常情况下,leader挂掉了产生数据不一致的情况下,ZAB如何保持数据的一致性。如何选出leader能够避免数据不一致的情况。

Zab提出,以下两种情况的数据不一致需要被解决:

1.事务到达leader后,还没proposal到follower leader挂掉 抛弃

2.事务达到leader后,proposal完,leader发commit请求后立即挂掉,follower没收到commit 最终能被处理

崩溃恢复需要解决上面两种情况下的数据不一致。大家可以考虑下为什么只有这两种状态,是否会存在比如1.一个事务提交到follower,然后follow挂了没发向leader,或者2.leader接受到请求但是没发出proposal就挂了,或者3.leader发了proposal但是并且已经收到一部分follower的ack的场景。上面说的场景有些没有控制消息丢失 比如1,2,并且这种场景下不是引起数据不一致。

换言之,zab协议崩溃恢复只关心两种场景

1.确保丢弃那些只在Leader服务器上被提出的事务

2.确保那些已经在Leader上提交的事务最终被所有服务器都提交

这就是他的原则

Leader选举算法 很简单,找所有机器中拥有最大ZXID的事务Proposal的服务器。1.可以保证新Leader一定具有所有已经提交的事务。2.可以省去Leader服务器检查Proposal的提交和废弃。

数据同步

崩溃恢复其实分为两部分,一个是崩溃以后Leader选举,第二个是数据恢复,恢复完以后才能进行正常的消息广播。

ZXID设计

ZXID由64位数字组成,其中低32位可以看做一个单调递增的计数器,针对客户端的每一次请求会逐次递增。高32位代表leader周期的epoch(世纪)编号,每次选举这个epoch会加1并重置低32位从0开始。

基于这种策略,对于上面的情况:

事务到达leader后,还没proposal到follower leader挂掉

这台机子如果重启了,如何废弃这个没有被push的proposal呢? 因为他的epoch比当前集群的epoch要小,所以他不会成为leader.(其实这边有点疑问,如果Leader挂了以后秒重启,这个时候集群是立即选举出新的leader确定新的epoch么,如果不是的话,那重新加进来的老leader 他的ZXID就是最大的了啊)

Leader服务器为每一个follower准备一个队列,与follower之间进行比对,并将没有被各Follower服务器同步的事务以Proposal消息的形式逐个发送,并在每一个Proposal后发在发送一个commit请求,如果follower是之前崩溃的leader,其中包含未被commit的proposal的话 会要求follower回退。等到所有的follower同步完proposal后并应用到内存数据库后,Leader再将此follower移到Follower队列。

你可能感兴趣的:(Zookeeper的ZAB协议)