ZooKeeper 集群结构与 Zab 协议:分布式一致性的基石
ZooKeeper 作为分布式协调服务,其高可用性和强一致性依赖于精巧的集群架构和 Zab 协议。集群通过 Leader-Follower 角色分工实现负载均衡与容错,而 Zab 协议则保证了数据在分布式节点间的一致性同步。以下深入解析集群结构、Zab 协议的工作原理及核心流程。
集群节点角色与架构
ZooKeeper 集群采用主从架构,节点分为三种角色,各司其职以保证集群稳定运行:
| 角色 | 功能描述 |
|---|---|
| Leader | 1. 处理所有写请求(事务请求),生成全局唯一的 zxid; 2. 发起投票并协调 Follower 完成数据同步; 3. 负责 Leader 选举过程中的投票与决策。 |
| Follower | 1. 处理读请求,转发写请求给 Leader; 2. 参与 Leader 选举(投票); 3. 同步 Leader 的数据,保证与 Leader 状态一致。 |
| Observer | 1. 仅处理读请求,不参与 Leader 选举和写请求投票; 2. 同步 Leader 数据,扩展集群读能力(适合读多写少场景)。 |
集群核心特性
- 过半存活原则:集群只要有超过半数的节点存活(如 3 节点集群至少 2 个存活),即可正常提供服务,保证分区容错性。
- 数据一致性:所有节点在内存中维护相同的数据集,Leader 通过 Zab 协议将写操作同步到 Follower/Observer,确保全局数据一致。
Zab 协议:分布式一致性的核心协议
Zab(ZooKeeper Atomic Broadcast)协议是 ZooKeeper 实现分布式一致性的底层协议,其核心目标是:在分布式环境下,保证事务操作的原子性和顺序性,最终使所有节点的数据达成一致。
Zab 协议分为两个核心阶段:Leader 选举(Leader Election) 和 原子广播(Atomic Broadcast)。
阶段一:Leader 选举(Leader Election)
当集群启动或 Leader 故障时,需通过选举产生新 Leader,确保集群恢复正常工作。
选举触发条件
- 集群首次启动,无 Leader;
- Leader 节点故障(如网络中断、进程崩溃),Follower 检测到心跳超时。
选举核心规则
节点通过比较三个关键值决定投票对象,优先级从高到低为:
- epoch(任期编号):每轮选举后递增的全局编号,代表 Leader 的 “任期”,值越大优先级越高;
- zxid(事务 ID):Leader 处理写请求时生成的全局唯一 ID(高 32 位为 epoch,低 32 位为自增序号),值越大表示数据越新;
- sid(服务器 ID):节点的唯一标识,值越大优先级越高(用于打破平局)。
选举流程(以 3 节点集群为例)
- 初始投票:每个节点首次投票给自己,广播投票信息(epoch=0,zxid=0,sid = 自身 ID)。
- 投票比较:节点收到其他节点的投票后,若对方的 epoch/zxid/sid 更高,则更新投票对象,重新广播。
- 达成共识:当某节点获得超过半数的投票(如 3 节点中获得 2 票),则当选为 Leader。
- 同步数据:新 Leader 与 Follower 同步数据,确保所有节点的 zxid 一致后,进入原子广播阶段。
阶段二:原子广播(Atomic Broadcast)
Leader 选举完成后,集群进入正常工作状态,所有写请求通过原子广播机制同步到集群节点,保证数据一致性。
广播流程(类似两阶段提交)
- 提议(Proposal):
- Leader 收到写请求后,生成全局唯一的 zxid(如
0x100000001),将请求封装为 “提议” 并广播给所有 Follower。
- Leader 收到写请求后,生成全局唯一的 zxid(如
- 投票(Ack):
- Follower 收到提议后,将数据写入本地事务日志,成功后向 Leader 返回 “确认(Ack)”。
- 提交(Commit):
- 当 Leader 收到超过半数 Follower 的 Ack 后,自身先提交该事务(更新内存数据),然后广播 “提交” 指令。
- Follower 收到提交指令后,最终提交事务,完成数据更新。
核心保证
- 原子性:事务要么全集群提交,要么全失败,无部分提交;
- 顺序性:所有事务按 zxid 递增顺序执行,保证全局时序一致。
zxid:事务与任期的全局标识
zxid(ZooKeeper Transaction ID)是 Zab 协议中用于标识事务的全局唯一 ID,由两部分组成(64 位):
- 高 32 位:epoch(任期编号),每轮 Leader 选举后递增,代表 Leader 的 “统治周期”;
- 低 32 位:事务序号,Leader 处理写请求时自增,标识同一任期内的事务顺序。
示例:
- zxid=0x100000001 表示:epoch=1(第 1 任 Leader),事务序号 = 1(该任期内第 1 个事务);
- zxid=0x200000005 表示:epoch=2(第 2 任 Leader),事务序号 = 5(该任期内第 5 个事务)。
zxid 的递增特性保证了事务的全局顺序性,是节点间数据同步和一致性校验的核心依据。
集群数据同步机制
Leader 与 Follower 之间通过 “数据同步” 保证状态一致,同步过程发生在:
- 新 Leader 选举完成后(确保所有节点追上 Leader 的数据);
- 新 Follower 加入集群时(从 Leader 同步历史数据)。
同步方式
- 增量同步:Follower 仅同步自身缺失的事务(通过比对 zxid 确定差异);
- 全量同步:若 Follower 缺失的事务过多(如长时间离线),Leader 会发送完整的数据快照,Follower 加载快照后再增量同步后续事务。