ZooKeeper的ZAB协议
ZAB(ZooKeeper Atomic Broadcast)协议并不像Paxos那样,是一种通用的分布式一致性算法,它是一种特别为ZooKeeper设计的崩溃可恢复的原子消息广播协议。在ZooKeeper中,主要依赖ZAB协议来实现分布式数据一致性,基于该协议,ZooKeeper实现了一种主备模式的系统架构来保持集群中各副本之间数据的一致性。
ZAB协议的核心是定义了那些会改变ZooKeeper服务器数据状态的事务请求的处理方式,即:所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器称为Leader服务器,而余下的服务器则成为Follower服务器。Leader服务器负责将一个客户端请求转换成一个事务Proposal(提议),并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有的Follwer服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向所有Follower服务器分发Commit消息,要求将前一个Proposal进行提交。
消息广播
ZAB协议使用的消息广播是一个原子广播协议。
- Leader服务器为每个Follower服务器分配一个FIFO队列,存储并广播事务Proposal
- 每个Follower服务器在接收到事务Proposal后,将其以事务日志的形式写入到本地磁盘,若成功反馈Ack响应
- Leader服务器若收到半数以上的Follower的Ack响应,向所有Follower服务器广播一个Commit消息,同时Leader服务器完成自身对事务的提交
- 每个Follower服务器在收到Commit之后会对事务进行提交
崩溃恢复
ZAB协议规定了如果一个事务Proposal在一台机器上被处理成功,那么应该在所有的机器上都被处理成功,哪怕机器出现故障崩溃。为了处理崩溃恢复可能出现的数据不一致,ZAB进行需要保证如下的特性。
ZAB协议需要确保已经在Leader服务器提交的事务,最终被所有服务器提交
可能出现数据不一致的地方:一个事务得到半数以上的Follower服务器的Ack反馈,并且Leader服务器上成功提交,但是在它将Commit消息发送给Follower服务器之前崩溃了ZAB协议需要确保丢弃那些只在Leader服务器上被提出的事务
可能出现数据不一致的地方:如果该事务没有被丢弃,那么在该Leader服务器从新加入集群,成为一个Follower服务器之后,可能就丢弃新接收的事务
数据同步
完成Leader选举之后,Leader服务器首先确认事务日志中的所有Proposal是否都已经被集群中过半的机器提交了,即是否完成了数据同步。所有正常运行的服务器,要么成为Leader,要么成为Follower并和leader保持同步。
正常情况下的数据同步:
- Leader服务器为每个Follower服务器准备一个FIFO队列,并发送事务Proposal给每一个未完成同步的Follower服务器,在Proposal消息之后追加Commit消息,表示事务已经被提交
- Follower服务器将其所有未同步的事务Proposal同步到本地数据库之后,Leader服务器将该Follower服务器加入到真正可用的Follower列表中
ZAB协议处理需要被丢失的事务Proposal,使用64位的事务编号ZXID
低32位:可以看作是一个简单的单调递增的计数器,客户端的每一个事务请求,Leader服务器会在产生一个新事务Proposal时候,对计数器加1
高32位:Leader周期epoch的编号, 每当选举产生一个新的Leader服务器,就会从该ZXID中解析出对应的epoch值,然后对其进行加1操作,并将低32位置0,由此更新ZXID的值。
ZAB协议中的这一通过epoch编号来区分Leader周期的变化的策略,能够在Leader服务器崩溃恢复中保持数据一致性。
在崩溃恢复中,当一个包含了上一个周期尚未提交的事务Proposal的服务器,其肯定无法成为Leader服务器,因为当前集群一个Quorum集合,该集合中的机器一定包含了更高的epoch,因此新加入的机器的事务Proposal肯定不是最高,也就无法成为Leader。当该机器加入到集群中,以Follower角色连接上Leader服务器之后,Leader服务器会根据自己服务上提交的Proposal和Follower进行对比,Follower服务器会回退到一个状态一一集群中过半机器提交的最新事务Proposal。
ZAB协议和Paxos算法
二者的联系:
- 两者都存在一个类似于Leader进程的角色,由其负责协调多个Follower进程的运行
- Leader进程都会等待超过半数的Follower做出正反馈后,才会将一个提案进行提交
- 两者都存在一个标识来表示Leader周期(epoch和Ballot)
区别:
- 设计目标来看,ZAB协议主要用于构建一个高可用的分布式数据主备系统(当然还要保证数据一致性)
- 在Paxos算法的基础上,ZAB协议额外增加了一个同步阶段。在同步阶段,新的Leader会确保存在过半的Follower已经提交了之前Leader周期的所有事务Proposal;也保证了在新的Leader周期中提出事务Proposal前,所有的Follower都已经完成了对之前所有事务Proposal的提交。