ZAB(原子消息广播协议)。在Zookeeper中,主要依赖ZAB协议来实现分布式数据一致性。
Zookeeper使用一个单一的主进程来接收并处理所有客户端的事务请求(也就是一个请求,如果说HTTP请求),并采用ZAB的原子广播协议,将服务器的数据状态变更以事务提议的方式广播到所有的副本进程上。
ZAB的核心是定义了事务请求的处理方式,即
ZAB协议包括2个基本的模式:消息广播 和 崩溃恢复
ZAB的消息广播过程使用的是原子广播协议,类似于二阶段提交。针对客户端的请求,Leader服务器生成对应的事务提议,并将其发送给集群中所有的Follower服务器。然后收集各自的选票,最后进行事务提交。如图:
在ZAB协议中的二阶段提交,移除了中断逻辑。所有的Follower服务器要么正常反馈Leader提出的事务提议,要么就抛弃Leader服务器。同时,我们可以在过半的Follower服务器已经反馈ACK后,就开始提交事务提议了。
Leader服务器会为事务提议分配一个全局单调递增的ID,称为事务ID(ZXID)。由于ZAB协议需要保证每一个消息严格的因果关系,因此需要将每一个事务提议按照其ZXID的先后顺序进行处理。
在消息广播过程中,Leader服务器会为每一个Follower服务器分配一个队列,然后将事务提议依次放入到这些队列中去,并且根据FIFO的策略进行消息发送。
每一个Follower服务器接收到这个事务提议后,会把该事务提议以事务日志的形式写入到本地磁盘中,并且写入成功后,反馈给Leader服务器ACK。
当Leader服务器收到过半Follower服务器的ACK,就发送一个COMMIT消息,同时Leader自身完成事务提交,Follower服务器接收到COMMIT消息后,也进行事务提交。
之所以采用原子广播协议协议,是为了保证分布式数据一致性。过半的节点数据保存一致性。
篇幅较大,单独的文章讲解
完成Leader选举之后,在正式开始工作之前,Leader服务器会去确认事务日志中所有事务提议(指已经提交的事务提议)是否都已经被过半的机器提交了,即是否完成数据同步。下面是ZAB协议的 数据同步过程。
Leader服务器为每一个Follower服务器准备一个队列,将那些没有被Follower服务器同步的事务以事务提议的形式逐个发送给Follower服务器,并在每一个事务提议消息后面发送一个commit消息,表示该事务已被提交。
等到Follower服务器将所有其未同步的事务提议都从Leader服务器上面同步过来,并且应用到本地数据库后,Leader服务器就会将该Follower服务器加入到真正可用的Follower列表中。
ZXID是一个64位的数字。
其中低32位是一个简单的单调递增的计数器,Leader服务器产生一个新的事务提议的时候,都会对该计数器+1。
高32位,用来区分不同的Leader服务器。具体做法是,每选举产生一个新的Leader服务器,就会从Leader服务器的本地日志中取出一个最大的ZXID,生成对应的epoch值,然后再进行加1操作,之后就会以该值作为新的epoch。并将低32位从0开始生成ZXID。(我理解这里的epoch代表的就是一个Leader服务器的标志,每次选举Leader服务器,那么epoch值就会更新,代表是这段时期由这个新的Leader服务器进行事务请求的处理)。
ZAB协议中通过epoch编号来区分Leader周期变化,能够有效避免不同Leader服务器使用相同的ZXID。
Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。
在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。
Paxos算法有3个角色:
分为2阶段
ZAB协议并不是Paxos算法的一个典型实现,在讲解ZAB和Paxos的区别之前,我们先来看看两者的联系:
在Paxos的基础上,ZAB协议额外增加了一个同步阶段。 在选举结束后,进入同步阶段,新的Leader会确保存过半的Follower已经提交了上一个Leader周期中的所有事务提议。