ZAB协议概念

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

表现形式

使用一个单一的主进程来接收并处理客户端的所有事务请求(写请求);
并采用ZAB的原子广播协议,将服务器数据的状态变更以事务Proposal(提案)的形式广播到所有的副本进程中。

架构保证

ZAB协议的主备模型架构保证了同一时刻,集群中只能够有一个主进程来广播服务器的状态变更,因此能够很好的处理客户端大量的并发请求。
ZAB协议会保证在主进程出现崩溃或重启的现象时,依然能够正常工作。

协议核心

核心:定义了对于会改变Zookeeper服务器数据状态的事务请求处理方式。

  • Leader服务器负责将一个客户端事务请求转化为Proposal,并将Proposal分发给集群中所有Follower服务器;
  • 之后Leader服务器需要等待所有Follower服务器的反馈(ACK);
  • 一旦超过半数的Follower服务器进行了正确的反馈(ACK),那么Leader就会再次向所有的Follower服务器分发Commit(提交)消息,要求Follower服务器将前一个Proposal进行提交。

    Leader服务器:所有的事务必须由一个全局唯一的服务器来协调处理。 Follower服务器:负责接收Leader服务器的事务提案与事务提交信息。

image.png

ZAB协议介绍

ZAB协议包括两种基本模式,崩溃恢复和消息广播

崩溃恢复模式

当整个服务框架启动过程中,或者是Leader服务器出现网络中断、崩溃退出或重启等异常情况下,ZAB就会进入崩溃恢复模式,重新选举产生新的Leader服务器。
当选举产生了新的Leader服务器,同时集群中已经有过半的机器与该Leader服务器完成状态同步之后,ZAB协议就会退出恢复模式。

状态同步:指的就是数据同步,用来保证集群中的过半的机器能够和Leader服务器的数据状态保持一致。

当一台同样遵守ZAB协议的服务器启动后加入集群中,如果此时集群中已经存在一个Leader服务器在负责进行消息广播,那么加入的服务器就会自觉进入数据恢复模式(找到Leader所在的服务器,进行数据同步,然后参与到消息广播的流程中)。

消息广播模式

当集群中已经有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个服务框架就可以进入消息广播模式。
Zookeeper只允许唯一一个Leader服务器来进行事务请求的处理,Leader服务器在接收客户端的事务请求后,会生成对应的事务Proposal并发起一轮广播协议。如果是非Leader服务器收到客户端的事务请求,那么非Leader服务器就会先将这个事务请求转发给Leader服务器。

ZAB协议模式具体过程

崩溃恢复模式过程

ZAB协议的基于原子广播协议过程中,在正常情况下运行良好。但是一旦在Leader服务器出现崩溃,或者由于网络原因导致Leader服务器失去了与过半Follower的联系,就会进入崩溃恢复模式。
在ZAB协议中,为了保证程序的正确运行,整个恢复过程结束后需要选举出一个新的Leader服务器。
需要保证快速进行选举出Leader服务器,并需要让集群中的所有机器(Leader服务器,Follower服务器,Observer服务器)能够快速感知选举出来的新的Leader服务器。

基本特性

ZAB协议规定,如果一个事务Proposal在一台机器上被处理成功,那么应该在所有的机器上都被处理成功,哪怕及其出现故障崩溃。
崩溃过程中出现数据不一致的隐患
1、在集群正常运行的过程中,Leader服务器在将Proposal(P1)提议发出之后崩溃了,此时会导致集群中的其他服务器没有接收到这个事务Proposal(P1)。
2、在集群正常运行的过程中,Leader服务器在将针对Proposal(P1)的提交信息Commit(C1)发出之后崩溃了,此时就会导致集群中的其他服务器没有收到这个提交信息Commit(C1)。
解决特性
1、ZAB协议需要确保丢弃那些只在Leader服务器上被提出的事务(提案Proposal的事务)。
2、ZAB协议需要保证已经在Leader服务器上提交的事务最终都被所有服务器提交(提交Proposal的事务)。
Leader选举算法
1、能够保证所有Follower提交已经被Leader服务器提交的事务Proposal。
2、能够丢弃已经被跳过的事务Proposal。
针对以上2点要求,Leader选举算法只要保证新选举出来的Leader服务器拥有集群中所有机器的最高事务编号(ZXID最大)的事务Proposal,那么就可以保证这个新选举出来的Leader服务器一定具有所有已经提交的事务提案。同时,如果让具有最高编号的事务Proposal的机器来成为Leader,就可以省去Leader服务器检查Proposal的提交和丢弃工作的这部分操作。

数据同步

完成Leader选举之后,在正式开始工作(即接收客户端事务请求,然后提出新提案)之前,Leader服务器就会首先确认事务日志的所有Proposal是否都已经被集群中过半的机器提交了,即是否完成了数据同步。
数据同步过程
Leader服务器需要确保所有的Follower服务器都能够接收到每一条Proposal。
并且能够正确地将所有已经提交了事务Proposal应用到内存数据库当中。
具体操作:
1、Leader服务器会为每一个Follower服务器都准备一个队列;
2、将没有被各个Follower服务器同步的事务以Proposal消息的形式逐个发送给Follower服务器;
3、并在每一个Proposal消息后面紧接着再发送一个Commit消息,以表示该事务已经被提交;
4、等到所有的Follower服务器将所有其尚未同步的事务Proposal都从Leader服务器同步过来并成功应用到本地数据库中后,Leader服务器就会将该Follower服务器加入到真正可用的Follower列表中,并开始之后的其他流程。

消息广播模式过程

ZAB协议的消息广播过程使用原子广播协议。类似于一个二阶段提交过程,针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,并将其发送给集群中其余的机器,然后再分别收集各自的选票,最后进行事务提交。
image.png
在ZAB的二阶段提交过程中,移除了中断逻辑,所有的Follower服务器要么正常反馈Leader提出的事务Proposal,要么就抛弃Leader服务器。同时,ZAB协议将二阶段提交的中断逻辑移除意味着我们可以在过半的Follower服务器都反馈ack之后就可以开始提交事务Proposal,而不需要等待集群中所有的Follower服务器都反馈响应。
但是,这种简化的二阶段提交模型,无法处理因为Leader服务器崩溃退出带来的数据不一致的问题。因此ZAB协议采用了崩溃恢复模式来解决此问题。
整个消息广播协议是基于具有FIFO特性的TCP协议来进行网络通信的,因此能够很容易保证消息广播过程中消息接收与发送的顺序性。

具体过程

1、在消息广播过程中,Leader服务器会为每一个Follower服务器都各自分配一个单独的队列,然后将需要广播的事务Proposal一次放入这些队列中,并根据FIFO策略进行消息发送。
2、每一个Follow服务器在接收到事务Proposal之后,都会首先将其以事务日志的形式写入到本地磁盘中,并在成功写入之后反馈给Leader服务器一个ACK响应。
3、当Leader服务器接收到超过半数的Follower的ACK响应之后,就会广播一个Commit消息给所有的Follower服务器,用来通知进行事务提交,同时Leader服务器自身也会完成对事务的提交,每一个Follower在接收到Commit消息后,就会完成对事务的提交。

ZAB协议运行状态分析

运行状态分类

在ZAB协议的设计中,每个进程都可能处于如下三种状态

  • LOOKING:Leader选举阶段。
  • FOLLOWING:Follower服务器和Leader保持同步状态阶段。
  • LEADERING:Leader服务器作为主进程领导状态。

    运行流程状态变更

    所有进程的初始状态都是LOOKING状态,此时不存在Leader。
    接着,所有的进程会试图选举一个新的Leader,如果后面进程发现选举出新的Leader了,就会切换为FOLLOWING状态,并开始与Leader保持数据同步。(处于FOLLOWING状态的进程称为Follower,处于LEADERING状态的进程称为Leader)。
    当Leader崩溃或者放弃领导地位时,其余的Follower进程就会转换到LOOKING状态并开始新一轮的Leader选举。

心跳检测机制作用

一个Follower只能和一个Leader保持同步。
Leader进程和所有的Follower进程之间通过心跳检测机制来感知彼此的情况。
若Leader服务器能够在超时时间内正常收到心跳检测,那么Follower就会一直与Leader保持连接;而如果在指定时间内Leader无法从过半Follower进程哪里接收到心跳检测,或者是TCP连接中断,那么Leader会放弃当前周期(epoch)的领导,并转换为LOOKING状态,其他的Follower会放弃这个Leader,同时转换为LOOKING状态,之后会进行新一轮的Leader选举。

ZAB与Paxos的联系和区别

联系

(1)都存在一个类似Leader进程的角色,由其负责协调多个Follower进程的运行。
(2)Leader进程都会等待超过半数的Follower做出正确的反馈后,才会将一个提议进行提交。
(3)在ZAB协议中,每一个Proposal都包含一个epoch值,用来代表当前的Leader周期。在Paxos算法中,同样存在这样的标识,名字为Ballot。

区别

(1)Paxos算法中,新选举出来的主(Master)进程会进行两阶段的工作。第一阶段称为读阶段,新的主进程和其他进程通信来收集主进程的提议,并将它们提交。第二阶段称为写阶段,当前主进程开始提出自己的提议。
(2)ZAB协议在Paxos基础上添加了同步阶段。此时,新的Leader会确保 存在过半的Follower已经提交了之前的Leader周期中的所有事务的Proposal。这个同步阶段的引入,能够有效保证Leader在新的周期中提出事务Proposal之前,所有的进程都已经完成了对之前所有事务的Proposal的提交。
(3)总的来说,ZAB协议和Paxos算法的区别在于,两者的设计目标不太一样,ZAB协议主要用于构建一个高可用的分布式数据主备系统,而Paxos算法则用于构建一个分布式的一致性状态机系统。