Zookeeper ZAB协议实现源码分析( 三 )


Zab 协议如何保证数据一致性假设两种异常情况:

  1. 一个事务在 Leader 上提交了 , 并且过半的 Folower 都响应 Ack 了 , 但是 Leader 在 Commit 消息发出之前挂了 。
  2. 假设一个事务在 Leader 提出之后 , Leader 挂了 。
要确保如果发生上述两种情况 , 数据还能保持一致性 , 那么 Zab 协议选举算法必须满足以下要求:
Zab 协议崩溃恢复要求满足以下两个要求:
  1. 确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交 。
  2. 确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal 。
根据上述要求 Zab协议需要保证选举出来的Leader需要满足以下条件:
  1. 新选举出来的 Leader 不能包含未提交的 Proposal  。
即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点 。
  1. 新选举的 Leader 节点中含有最大的 zxid  。
这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作 。
Zab 如何数据同步
  1. 完成 Leader 选举后(新的 Leader 具有最高的zxid) , 在正式开始工作之前(接收事务请求 , 然后提出新的 Proposal) , Leader 服务器会首先确认事务日志中的所有的 Proposal 是否已经被集群中过半的服务器 Commit 。
  2. Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务的 Proposal  , 并且能将所有已经提交的事务 Proposal 应用到内存数据中 。等到 Follower 将所有尚未同步的事务 Proposal 都从 Leader 服务器上同步过啦并且应用到内存数据中以后 , Leader 才会把该 Follower 加入到真正可用的 Follower 列表中 。
Zab 数据同步过程中 , 如何处理需要丢弃的 Proposal在 Zab 的事务编号 zxid 设计中 , zxid是一个64位的数字 。
其中低32位可以看成一个简单的单增计数器 , 针对客户端每一个事务请求 , Leader 在产生新的 Proposal 事务时 , 都会对该计数器加1 。而高32位则代表了 Leader 周期的 epoch 编号 。
epoch 编号可以理解为当前集群所处的年代 , 或者周期 。每次Leader变更之后都会在 epoch 的基础上加1 , 这样旧的 Leader 崩溃恢复之后 , 其他Follower 也不会听它的了 , 因为 Follower 只服从epoch最高的 Leader 命令 。
每当选举产生一个新的 Leader  , 就会从这个 Leader 服务器上取出本地事务日志最大编号 Proposal 的 zxid , 并从 zxid 中解析得到对应的 epoch 编号 , 然后再对其加1 , 之后该编号就作为新的 epoch 值 , 并将低32位数字归零 , 由0开始重新生成zxid 。
Zab 协议通过 epoch 编号来区分 Leader 变化周期 , 能够有效避免不同的 Leader 错误的使用了相同的 zxid 编号提出了不一样的 Proposal 的异常情况 。
基于以上策略: 当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal 的服务器启动时 , 当这台机器加入集群中 , 以 Follower 角色连上 Leader 服务器后 , Leader 服务器会根据自己服务器上最后提交的 Proposal 来和 Follower 服务器的 Proposal 进行比对 , 比对的结果肯定是 Leader 要求 Follower 进行一个回退操作 , 回退到一个确实已经被集群中过半机器 Commit 的最新 Proposal 。
Zab实现原理Zab 节点有三种状态
  • Following:当前节点是跟随者 , 服从 Leader 节点的命令 。
  • Leading:当前节点是 Leader , 负责协调事务 。
  • Election/Looking:节点处于选举状态 , 正在寻找 Leader 。
代码实现中 , 多了一种状态:Observing 状态 这是 Zookeeper 引入 Observer 之后加入的 , Observer 不参与选举 , 是只读节点 , 跟 Zab 协议没有关系 。
节点的持久状态
  • history:当前节点接收到事务 Proposal 的Log
  • acceptedEpoch:Follower 已经接收的 Leader 更改 epoch 的 newEpoch 提议 。
  • currentEpoch:当前所处的 Leader 年代
  • lastZxid:history 中最近接收到的Proposal 的 zxid(最大zxid)
Zab 的四个阶段
  1. 选举阶段(Leader Election)
节点在一开始都处于选举节点 , 只要有一个节点得到超过半数节点的票数 , 它就可以当选准 Leader , 只有到达第三个阶段(也就是同步阶段) , 这个准 Leader 才会成为真正的 Leader 。


推荐阅读