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


Zookeeper ZAB协议实现源码分析

文章插图
 
Zab协议内容Zab 协议包括两种基本的模式:崩溃恢复 和 消息广播
协议过程当整个集群启动过程中 , 或者当 Leader 服务器出现网络中弄断、崩溃退出或重启等异常时 , Zab协议就会 进入崩溃恢复模式 , 选举产生新的Leader 。
当选举产生了新的 Leader , 同时集群中有过半的机器与该 Leader 服务器完成了状态同步(即数据同步)之后 , Zab协议就会退出崩溃恢复模式 , 进入消息广播模式 。
这时 , 如果有一台遵守Zab协议的服务器加入集群 , 因为此时集群中已经存在一个Leader服务器在广播消息 , 那么该新加入的服务器自动进入恢复模式:找到Leader服务器 , 并且完成数据同步 。同步完成后 , 作为新的Follower一起参与到消息广播流程中 。
协议状态切换当Leader出现崩溃退出或者机器重启 , 亦或是集群中不存在超过半数的服务器与Leader保存正常通信 , Zab就会再一次进入崩溃恢复 , 发起新一轮Leader选举并实现数据同步 。同步完成后又会进入消息广播模式 , 接收事务请求 。
保证消息有序在整个消息广播中 , Leader会将每一个事务请求转换成对应的 proposal 来进行广播 , 并且在广播 事务Proposal 之前 , Leader服务器会首先为这个事务Proposal分配一个全局单递增的唯一ID , 称之为事务ID(即zxid) , 由于Zab协议需要保证每一个消息的严格的顺序关系 , 因此必须将每一个proposal按照其zxid的先后顺序进行排序和处理 。
消息广播
  1. 在zookeeper集群中 , 数据副本的传递策略就是采用消息广播模式 。zookeeper中数据副本的同步方式与二段提交相似 , 但是却又不同 。二段提交要求协调者必须等到所有的参与者全部反馈ACK确认消息后 , 再发送commit消息 。要求所有的参与者要么全部成功 , 要么全部失败 。二段提交会产生严重的阻塞问题 。
  2. Zab协议中 Leader 等待 Follower 的ACK反馈消息是指“只要半数以上的Follower成功反馈即可 , 不需要收到全部Follower反馈”

Zookeeper ZAB协议实现源码分析

文章插图
 
消息广播具体步骤
  1. 客户端发起一个写操作请求 。
  2. Leader 服务器将客户端的请求转化为事务 Proposal 提案 , 同时为每个 Proposal 分配一个全局的ID , 即zxid 。
  3. Leader 服务器为每个 Follower 服务器分配一个单独的队列 , 然后将需要广播的 Proposal 依次放到队列中去 , 并且根据 FIFO 策略进行消息发送 。
  4. Follower 接收到 Proposal 后 , 会首先将其以事务日志的方式写入本地磁盘中 , 写入成功后向 Leader 反馈一个 Ack 响应消息 。
  5. Leader 接收到超过半数以上 Follower 的 Ack 响应消息后 , 即认为消息发送成功 , 可以发送 commit 消息 。
  6. Leader 向所有 Follower 广播 commit 消息 , 同时自身也会完成事务提交 。Follower 接收到 commit 消息后 , 会将上一条事务提交 。
zookeeper 采用 Zab 协议的核心 , 就是只要有一台服务器提交了 Proposal , 就要确保所有的服务器最终都能正确提交 Proposal 。这也是 CAP/BASE 实现最终一致性的一个体现 。
Leader 服务器与每一个 Follower 服务器之间都维护了一个单独的 FIFO 消息队列进行收发消息 , 使用队列消息可以做到异步解耦 。Leader 和 Follower 之间只需要往队列中发消息即可 。如果使用同步的方式会引起阻塞 , 性能要下降很多 。
崩溃恢复一旦 Leader 服务器出现崩溃或者由于网络原因导致 Leader 服务器失去了与过半 Follower 的联系 , 那么就会进入崩溃恢复模式 。
在 Zab 协议中 , 为了保证程序的正确运行 , 整个恢复过程结束后需要选举出一个新的 Leader 服务器 。因此 Zab 协议需要一个高效且可靠的 Leader 选举算法 , 从而确保能够快速选举出新的 Leader。
Leader 选举算法不仅仅需要让 Leader 自己知道自己已经被选举为 Leader  , 同时还需要让集群中的所有其他机器也能够快速感知到选举产生的新 Leader 服务器 。
崩溃恢复主要包括两部分:Leader选举 和 数据恢复


推荐阅读