一致性协议:ZAB

一致性协议:ZAB

ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务ZooKeeper专门设计的一种支持崩溃恢复的原子广播协议。 在ZooKeeper中,主要依赖ZAB协议来实现分布式数据一致性,基于该协议,ZooKeeper实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

ZAB协议包括了两种基本的模式,分别是崩溃恢复消息广播

消息广播

为了保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致,ZAB协议中引入了消息广播模式。

在上面我们提到了,ZooKeeper集群中只有Leader服务器能够执行写操作,为了保证集群的数据一致性,我们需要将Leader节点更新的数据同步到Follower与Observer服务器中,所以当Leader服务器接收到客户端发送的写请求后,会自动生成对应的提案并发起一轮消息广播。

消息广播的执行流程如下:

  1. 接受到客户端发送的事务请求,Leader服务器为其生成对应的事务提议。
  2. Leader为每一个Follower和Observer都准备了一个FIFO的队列,并把提议发送到队列上。
  3. 当Follower接收到事务提议后,都会先将其以事务日志的形式写入本地磁盘中,然后再写入成功后反馈给Leader服务器一个ACK。
  4. 当Leader接收到半数以上Follower节点的ACK,它就会认为大部分节点都同意议题,准备开始提交。
  5. Leader向所有节点发送提交事务的Commit请求,完成事务。

为了防止因为网络等原因导致的Follower、Observer节点处理请求的顺序不同而导致的数据不一致问题,保证消息广播过程中消息接收与发送的顺序性,消息广播中引入了FIFO队列事务ID来解决这个问题。

  • 在消息广播的过程中,Leader服务器会为每一个Follower、Observer服务器都各自分配一个单独的队列,然后将需要广播的事务提议放到这些队列中,并根据FIFO策略进行消息发送。由于ZAB由于协议是通过TCP协议来进行网络通信的,这样不仅保证了消息的发送顺序性,也保证了接受顺序性。
  • 在广播事务提议之前,Leader服务器会先给这个提议分配一个全局单调递增的唯一事务ID(ZXID)。为了保证每一个消息严格的因果关系,必须将每一个事务提议按照其ZXID的先后顺序来进行排序与处理。

如果你了解过二阶段提交(2PC)协议,你会发现其实消息广播的过程实际上就是一个简化版本的二阶段提交过程,他将二阶段提交中的中断逻辑删除,Leader服务器不需要等待集群中的全部Follower服务器都响应反馈,只需要得到过半Follower的ACK就开始执行事务的提交。这种简化版的2PC虽然提高了效率,但是无法处理Leader服务器崩溃退出而导致的数据不一致问题,因此ZooKeeper中又添加了崩溃恢复模式来解决这个问题。

崩溃恢复

当Leader服务器出现崩溃退出或机器重启,亦或是集群中不存在半数以上的服务器与Leader服务器保持正常通信时,在重新开始新的一轮原子广播事务操作之前,此时所有节点都会使用崩溃恢复协议来使彼此达到一个一致的状态。

崩溃恢复过程需要确保那些已经在Leader服务器上提交的事务最终被所有的事务提交。

假设一个事务中Leader服务器(server2)上被提交了,并且已经得到了过半Follower服务器的ACK反馈,但是在它将Commit消息发送给所有的Follower机器之前,Leader服务器就挂掉了,如下图:

从上图可以看到,部分的节点收到了commit请求并进行了提交,而有一部分Leader还没来得及发送就已经崩溃了。针对这种情况,崩溃恢复必须要确保该事务最终能够在所有的服务器上都被提交成功,否则将会出现数据不一致的情况。所以在重新选举的时候,必定会选取ZXID最大的节点来确保其保留了最新的事件。

崩溃恢复过程需要确保丢弃那些只在Leader服务器上被提出的事务。

如果Leader服务器在提交了一个事务之后,还没来得及广播发送commit就已经崩溃推出了,从而导致集群中的其他服务器都没有收到这个事务提议。当原先的Leader节点故障恢复后,再次以Follower的角色加入集群后,此时就因为只有它完成了事务提交,而产生了数据不一致的情况,如下图:

针对这种情况,我们需要让server2在故障恢复后能够丢弃这些只在它这个节点上提出的事务,来确保数据一致。

为了能够满足上述的两个要求,所以ZooKeeper让Leader选举算法保证新选举出来的Leader服务器拥有集群中所有机器最高的事务编号(ZXID最大),那么这就肯定能够保证新选举出来的Leader一定具有所有已经提交的提案,此时新的Leader就会将事务日志中尚未提交的消息同步到各个服务器中。

Built with Hugo
主题 StackJimmy 设计