zookeeper之ZAB协议

1、基础概念

ZAB 协议全称:Zookeeper Atomic Broadcast(Zookeeper 原子广播协议)

2、消息广播

ZAB 协议的消息广播过程使用的是一个原子广播协议,类似一个 二阶段提交过程。

1:对于客户端发送的写请求,全部由 Leader 接收,Leader 接收到写请求消息请求后,将客户端的写请求消息,赋予一个全局唯一的64位自增id,叫:zxid,通过zxid的大小比较就可以实现因果有序这个特征。Leader 为每个follower准备了一个FIFO队列(通过TCP协议来实现,以实现全局有序这一个特点)将带有zxid的客户端的写请求封装成一个事务 Proposal,作为一个提案(proposal)分发给所有的 follower。

2:当follower接收到proposal,先把proposal写到磁盘,写入成功以后再向leader回复一个ack。

3:如果Leader接收到Follower超过半数的成功ack响应。

4:则向Follower发送commit消息,执行 commit 操作(先提交自己Leader的事务 Proposal(即执行客户端发送的写请求),再发送 commit 给所有 Follwer,让所有的Follwer也执行commit操作)。

3、崩溃恢复

1.ZAB 协议需要确保那些已经在 Leader 服务器上提交的事务最终被所有服务器都提交

假设一个事务在 Leader 服务器上被提交了,并且已经得到过半 Follower 服务器的Ack 反馈,但是在它将 Commit 消息发送给所有 Follower 机器之前, Leader 服务器挂了,针对这种情况, ZAB 协议就需要确保该事务最终能够在所有的服务器上都被提交成功,否则将出现不一致。

2.ZAB协议需要确保丢弃那些只在 Leader 服务器上被提出的事务

假设初始的 Leader 服务器 在提出了一个事务之后就崩溃退出了,导致集群中的其他服务器都没有收到这个事务,当该服务器恢复过来再次加入到集群中的时候 ,ZAB协议需要确保丢弃这个事务。
针对这些问题,ZAB 定义了 2 个原则:

ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。
ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。

ZAB 设计了下面这样一个选举算法:
能够确保提交已经被 Leader 提交的事务,同时丢弃已经被跳过的事务。
针对ZAB 协议需要确保那些已经在 Leader 服务器上提交的事务最终被所有服务器都提交这个要求:
如果leader选举算法能够保证新选举出来的Leader服务器,拥有集群中所有机器最高编号(ZXID 最大)的事务Proposal,那么就可以保证这个新选举出来的leader一定具有已经提交的提案。因为所有提案被commit之前必须有超过半数的follower ack,即必须有超过半数节点的服务器的事务日志上有该提案的proposal,因此只要有合法数量的节点正常工作,就必然有一个节点保存了所有被commit消息的proposal状态。 这样ZAB 协议就保证了那些已经在 Leader 服务器上提交的事务最终被所有服务器都提交
另外一个,zxid是64位,高32位是epoch编号,每经过一次Leader选举产生一个新的leader,新的leader会将epoch号+1,低32位是消息计数器,每接收到一条消息这个值+1,新leader选举后zxid这个值重置为0。这样设计的好处在于老的leader挂了以后重启,它不会被选举为leader,因此此时它的zxid肯定小于当前新的leader。当老的leader作为follower接入新的leader后,新的leader会让它将所有的拥有旧的epoch号的未被commit的proposal清除。
针对ZAB协议需要确保丢弃那些只在 Leader 服务器上被提出的事务这个要求:

下面来看 ZAB 协议是如何处理那些需要被丢弃的事务 Proposal 的:

在 ZAB 协议的事务编号 ZXID 设计中, ZXID 是一个 64 位的数字,低 32 位可以看作是一个简单的单调递增的计数器,针对客户端的每一个事务请求, Leader 服务器在产生一个新的事务 Proposal 的时候,都会对该计数器进行加1操作;高 32 位代表了 Leader 周期 epoch 的编号,每当选举产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出其本地日志中最大事务 Proposal 的 ZXID ,并从该 ZXID 中解析出对应的 epoch 值,然后再对其进行加1操作,之后就会以此编号作为新的 epoch, 并将低 32 位,置为0来开始生成新的 ZXID 。

基于这样的策略,当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal的服务器启动加入到集群中,发现此时集群中已经存在leader,将自身以Follower 角色连接上 Leader 服务器之后, Leader 服务器会根据自己服务器上最后被提交的 Proposal来和 Follower 服务器的 Proposal进行比对,发现follower中有上一个leader周期的事务Proposal时(上一个leader周期指的是上一个epoch),Leader 会要求 Follower 进行一个回退操作(回滚操作)——回退到一个确实已经被集群中过半机器提交的最新的事务 Proposal 。(改朝换代了,新皇帝登基了,旧的皇帝的指令当然是不好使的了,新的王朝要听新的帝王的指令)
  基于这样的策略:当 Follower 链接上 Leader 之后,Leader 服务器会根据自己服务器上最后被提交的 ZXID 和 Follower 上的 ZXID 进行比对,比对结果要么回滚,要么和 Leader 同步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值