ZooKeeper ZAB协议简述

小伙伴们如有错误,欢迎交流

Zookeeper主要依赖ZAB(ZooKeeper Atomic Broadcast)协议实现分布式数据的一致性,基于该协议,ZooKeeper实现了一种主备模式的系统架构来保持集群中各副本之间的数据一致性。具体的说:
1. ZooKeeper使用一个单一的主进程(单进程更好处理客户端并发)来接收并处理客户端的事务请求,并采用ZAB原
子广播协议将服务器数据的状态变更以事务Proposal形式广播到所有的副本进程上去。
2. ZAB协议也保证如果一个状态变更被处理了,那么所有其依赖的状态变更也被提前处理了。
3. ZAB协议还要考虑在主进程出现异常的情况下依旧能够正常的工作.

ZAB协议的核心是定义了对于那些会改变ZooKeeper服务器数据状态的事务请求的处理方式,即:

所有事务请求必须由一个全局唯一的服务器也就是Leader来协调处理,而余下的其他服务器成为Follower服务器,Leader服务器负责将一个客户端的事务请求转换成一个事务Proposal,并将该Proposal分发给集群中所有的Follower服务器,之后Leader服务器等待Follower服务器的反馈,一旦超过了半数的Follower服务器进行了正确的反馈后,那么Leader就会要求Follower服务器分发Commit消息,要求其将前一个Proposal进行提交

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

当ZooKeeper服务框架在启动的过程中,或是当Leader服务器出现了网络中断,崩溃退出与重启等异常情况时,ZAB协议会进入恢复模式并选举产生新的Leader服务器.当选举产生了Leader服务器,并且服务器集群中有一半的机器与该Leader服务器完成了状态同步(就是数据同步)之后ZAB协议会退出恢复协议,整个服务器集群进入了消息广播模式。

当一台遵守ZAB协议的服务器崩溃启动后加入到集群中,如果此时已经存在一个Leader服务器在进行事务请求的处理,那么新加入的服务器自觉进入数据恢复模式,找到Leader服务器并与其进行数据同步,随后加入到数据广播。Leader服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议,如果集群中其它机器接收到客户端的事务请求,那么这些非Leader服务器会首先将这个事务请求转发给Leader服务器

若Leader服务器崩溃退,过半Follower服务器不能与Leader通信后,那么follower服务器在新一轮原子广播事务前,所有的进程会使用崩溃恢复协议使彼此达到一致的状态

一个机器要成为新的Leader必须获得过半进程的支持,同时由于每个进程都可能崩溃,ZAB协议运行过程中,前后会出现多个leader,并且每个进程都可能多次成为leader,只要有过半的机器彼此之间能够相互通信,那么就可以产生一个新的Leader并在此进入到消息广播模式

消息广播

ZAB协议的消息广播使用的是一个原子广播协议,类似于一个二阶段提交的过程,针对客户端的事务请求,Leader服务器会为其生成对应的事务proposal,并将其发送给集群中其余的所有机器,然后收集各自的选票最后进行事务的提交.所有Follower服务器要么正常反馈Leader服务器提出的事务要么就抛弃Leader服务器,ZAB协议的二阶提交与之前文章中所讲到的二阶提交不同点在于ZAB协议中Leader不用等待全部的Follower发送ACK响应就能提交事务,简化的二阶提交模型是无法处理Leader服务器崩溃带来的数据不一致问题的,所以ZAB协议会在崩溃恢复阶段解决数据不一致的问题

在消息广播过程中,Leader为每个事务请求生成对应的Proposal进行广播,Leader也会为每个Proposal生成全局单调递增的唯一Id即ZXID(ZXID是解决上文提到的数据不一致问题的关键点之一,它的生成算法以及如何利用ZXID解决数据不一致问题在崩溃恢复阶段会讲到),由于状态变更请求可能存在依赖关系,必须将每个事务Proposal按照ZXID先后顺序进行排序和处理.更详细的过程如下

在消息广播过程中,Leader服务器会为每个Follower服务器各自分配一个单独的队列,然后将需要的广播Proposal依次放入到这个队列中,并且根据先进先出策略进行消息发送,每一个Follower服务器在接受到这个事务Proposal之后,都会首先以事务日志的形式写入到本地磁盘中,并且在成功写入后返回给Leader ACK响应.当Leader服务器收到超过半数Leader服务器的响应后,就通知Follower提交事务,Leader自己也完成事务的提交

崩溃恢复

崩溃恢复主要用于解决Leader与超过半数的Follower失去连接的情况.ZAB协议规定如果一个事务proposal在一台机器上被成功处理,那么所有的机器都应该被处理成功.

我们考虑Leader崩溃条件下产生数据不一致的两种情况

情况一:假设一个事务在Leader服务器上被提交了,并且已经得到了过半Follower Ack反馈,但是在将commit消息发送给所有的Follower机器之后Leader服务器挂了,对于这种情况,ZAB协议需要确保事务在所有的服务器上被提交否则数据将会不一致

情况二:Leader服务器Server1在提出一个事务Proposal3后就崩溃退出了,从而导致其他服务器都没有收到这个事务,于是Server1恢复过来再次加入到集群中的时候,ZAB协议需要确保丢弃这个Proposal3事务

ZAB协议为了解决上述的两种情况需要确保以下两点
1. ZAB协议需要确保那些已经在Leader服务器上提交的事务最终被所有的服务器都提交
2. ZAB协议需要确保丢弃那些只在Leader服务器上被提出的事务

为了实现上述两点,Leader选举算法必须能够确保提交已经被Leader提交的事务proposal,同时丢弃已经被跳过的事务Proposal,针对这个要求,如果Leader选举算法拥有集群中最高编号(即ZXID最大)的事务Proposal,那么就可以确保选举出来的Leader一定具有所有已经提交的提案,更为重要的是如果让拥有最高编号的Proposal机器成为Leade可以忽略Leader服务器检查Proposal的提交和丢弃这一步的工作。这一部分是ZAB协议解决数据不一致问题的关键点之一.

接下来我们更详细的探讨ZAB如何解决数据不一致问题

Leader崩溃之后,Follower完成Leader选举之后,在接收客户端请求然后提出新的提案之前,新Leader服务器会首先确认事务日志中的所有Proposal是否被集群中过半的机器提交

接下来所有的Follower要和Leader进行数据同步,具体流程如下

Leader服务器为每个Follower服务器准备一个队列,并且将没有被各Follower服务器同步的事务以Proposal消息的形式逐个发送给Follower服务器,并在每个Follower服务器后面再跟一个Commit消息,表示该事务已经提交.等到Follower服务器将所有尚未同步的事务Proposal都从Leader服务器上同步过来并成功应用到本地数据库后,Leader服务器会将该Follower服务器加入到真正可用的Follower列表并开始之后的流程

ZAB协议如何处理需要被丢弃的Proposal的呢?

在ZAB协议的事务编号ZXID是一个64位的数字,其中低32位是一个简单的递增计数器,针对客户端的每个事务请求,Leader在产生一个新的proposal的时候都会对该计数器执行加一的操作,而高32位代表了Leader周期epoch编号,每当选举一个新的Leader操作,就从当前最大事务zxid解析出对应的epoch值加一作为新Leader epoch编号,而低32位则从0开始生成新的zxid

对于这样的策略,上一个Leader周期尚未提交的Proposal服务器启动时就肯定无法成为Leader,因为该集群中存在一个更高epoch事务的Proposal,因此这台机器成为Follower,然后该Follower会与当前的Leader同步数据,当前的Leader会要求Follower回退到一个确实已经被集群中过半机器提交的最新事务Proposal

再来回顾下ZAB协议是如何解决情况一和情况二的:

针对情况一:原Leader服务器在得到大部分Follower ACK响应后又发送准备commit命令,在commit命令发送之后原Leader服务器崩溃.通过选举产生新Leader之后,新Leader是拥有最大已提交proposal id的机器,随后原leader会与新leader进行数据同步提交未提交的数据

针对情况二:因为原Leader服务器刚提出了一个proposal还没来得及发送给其它Follower就崩溃了,也就是说新选举出的leader没有该proposal,原leader服务器崩溃重启后与新leader服务器进行数据同步,当前的Leader会要求Follower回退到一个确实已经被集群中过半机器提交的最新事务Proposal

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值