ZAB协议简介
Zookeeper 使用 Zookeeper Atomic Broadcast (ZAB) 协议来保障分布式数据一致性。
ZAB是一种支持崩溃恢复的消息广播协议,采用类似2PC的广播模式保证正常运行时性能,并使用基于 Paxos 的策略保证崩溃恢复时的一致性。
在阅读本文前建议先了解2PC和Paxos
ZAB协议中节点存在四种状态:
- Leading: 当前节点为集群 Leader,负责协调事务
- Following: 当前节点为 Follower 在 Leader 协调下执行事务
- Looking: 集群没有正在运行的 Leader, 正处于选举过程
- Observing: 节点跟随 Leader 保存系统最新的状态提供读服务,但不参与选举和事务投票
因为 Observing 节点不参与事务和选举,因此下文所述节点不包括 Observing 节点
ZAB协议存在两种工作模式:
- 广播模式: 当集群正常运行过程中,Leader 使用广播模式保证各 Follower 节点的一致性
- 恢复模式: 集群启动或 Leader 崩溃时系统进入恢复模式,选举 Leader 并将集群中各节点的数据同步到最新状态
Zookeeper 集群中每个节点都会存储系统数据的完整副本,可以独立处理读请求。
当 Follower 收到写请求时会将其转发给 Leader, Leader 为每个写请求分配唯一的全局有序的事务ID(Zookeeper Transaction Id, ZXID)。
Leader 在广播模式下协调各 Follower 完成事务,并保证集群更新到一致的状态。
一致性保证
ZAB协议保证集群的顺序一致性而不保证强一致性。
即 Leader 依次完成两个事务 A、B 时,不能保证所有 Follower 立即更新到最新状态(不保证强一致性); 只保证所有 Follower 一定时间内会同步到最新状态(保证最终一致性),且任意 Follower 都认为事务A先于事务B完成,不会乱序(保证全局顺序一致性)。
此外,ZAB协议保证来自同一个 Follower 的两个事务 A、B 按照 Follower 发出请求的顺序(而非 Leader 收到请求的顺序)依次执行,不会出现乱序。即保证任意客户端写请求的一致性。
ZXID
ZXID 是 Zookeeper 集群中事务的唯一标识,保证全局有序。
ZXID 是一个 64 位整数, 高32位为周期号(epoch), 每个 Leader 被选举后都会增加 epoch 与上任 Leader 区分。低32位是 Leader 开始事务时分配的递增编号。
ZXID 中的 epoch 可以保证 Leader 崩溃重新选举后被丢弃的事务不会继续执行。
广播模式#
广播模式是一个移除了中断逻辑的2PC协议:
- Leader 收到写请求后为其分配一个 ZXID 并生成提案发送给所有 Follower
- Follower 收到提案后写事务日志但不提交,成功后返回 ACK 告知 Leader 可以进行提交。
- Leader 收到过半 Follower 的 ACK 响应后发出 commit 请求执行提交
- Leader 收到过半 Follower 对 commit 请求的 ACK 响应后便认为事务已完成。剩余的 Follower 则会放弃执行此次事务,进入数据同步阶段,与集群达成一致。
ZAB广播模式相对于完整的2PC移除了中断逻辑, 且只要过半 Follower 完成即可不需要等待全部 Follower。
崩溃或网络超时的 Follower 可以直接抛弃 Leader,并在数据同步阶段与集群达成一致,这种做法提高了集群的性能。
因为无法保证所有 Follower 都完成了提交,所以 Zookeeper 无法保证强一致性。
Leader 为每个 Follower 的写请求维护了一个 FIFO 队列以保证顺序一致性,具体实现方式是根据 TCP 报文的序列号确定请求的先后顺序。
恢复模式#
当集群启动或者Leader崩溃时,Zookeeper 集群会进入恢复模式选举新的 Leader 并将集群同步至最新状态。
Leader 与过半的 Follower 无法正常通信即视为崩溃
在崩溃恢复过程中需要保证:
- 已执行的事务不能丢失(Never forget delivered messages)
- 未执行的事务不能继续执行(Let go of messages that are skipped)
若 Leader 在 commit 阶段崩溃,根据已完成的事务不能丢失的原则,这些事务应该继续完成。
因为集群中 ZXID 最大的提案是 Leader 崩溃前发出的最新的提案,所以应选择拥有 ZXID 最大的提案的节点做为新的 Leader。
新 Leader 会将自身日志中所有未提交事务重新生成提案并协调集群将其完成, 保证所有被发送的消息(delivered messages)都被处理。
若 Leader 在 proposal 阶段崩溃,根据未执行的事务不能继续的原则,节点应当丢弃这些事务。
当新 Leader 被选举之后会增加 ZXID 的 epoch 值,因此 epoch 值较小的提案可以直接丢弃。
恢复模式分为两个阶段:选举阶段和恢复阶段。
上文已经说明恢复阶段的任务是 Leader 将未提交事务重新生成提案并协调集群将其完成,不再赘述。
选举过程
选举要保证:
- 集群中有且只有一个节点作为 Leader, 该 Leader 可以与集群中过半节点通信
- 新 Leader 拥有 ZXID 最大的提案
在3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection选举算法
每张选票包含3条信息:
- vote_sid: 推举的服务器ID
- vote_zxid: 推举的服务器的最大ZXID
- epoch: 投票的轮数
发起选举的节点会向所有可通信节点发送第一张选票,推举自己作为 Leader。
收到选票的服务器根据下列规则决定自己的投票:
- 若 epoch 大于自身 epoch 说明上一轮投票已结束,更新自身 epoch 值加入新一轮投票,并清除已结束轮次的数据。
- 选择自身已知 拥有最大ZXID 的服务器作为 Leader。即服务器本地保存(vote_sid, vote_zxid)并初始化为自身(sid, zxid), 若收到的选票中 vote_zxid 更大就更新本地数据,并根据最新数据投出选票。
- 若存在 zxid 相同则选择 sid 最大的服务器(作者认为选择sid最小的也可以)。
若在某轮投票中某个节点收到过半数的相同选票,那么认为该服务器为新的 Leader 投票结束。
因为选举阶段要求服务器收到过半选票才能成为新 Leader, 因此不可能出现集群中存在两个 Leader 的现象。
选举过程是比较典型的 Paxos 算法过程,选举过程中不会产生新的 ZXID, 因此不会出现 Paxos 算法中活锁的现象。
关于ZAB协议的详细内容可以阅读官方论文ZooKeeper’s atomic broadcast protocol: Theory and practice。
作者:finley
出处:https://www.cnblogs.com/Finley/p/9787721.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南