ZooKeeper 选举算法详解:Paxos 与 ZAB 协议
⚠️先纠正一个常见误区:ZooKeeper 实际使用的不是 Paxos,而是ZAB 协议(ZooKeeper Atomic Broadcast,原子广播)。Paxos 是分布式共识算法的理论基石,ZAB 深受 Paxos 启发,但针对 ZooKeeper 的"选主 + 数据同步"场景做了专门改造。
本文先详解Paxos(理解理论基础),再讲ZAB(ZooKeeper 真正用的),最后对比 Raft。
一、背景:为什么需要"共识算法"?
分布式系统里,多个节点要对某个值(谁当 Leader、某条数据怎么写)达成一致,但节点可能故障、网络延迟、消息乱序。
**共识算法(Consensus)**要解决:在部分节点故障的情况下,让所有正常节点对同一个值达成一致。
- Paxos:Lamport 提出,理论奠基,被称为"最难理解的算法"
- ZAB:ZooKeeper 专用,选主 + 原子广播
- Raft:更易理解的工程化共识算法(Etcd 使用)
二、Paxos 算法详解(理论基础)
2.1 三种角色
| 角色 | 职责 |
|---|---|
| Proposer(提议者) | 提出一个值(如"我提议 A 当 Leader") |
| Acceptor(接受者) | 对提议投票,决定是否接受 |
| Learner(学习者) | 学习最终被接受的值(不参与投票) |
一个节点可以同时扮演多个角色。
2.2 核心原则:多数派(Quorum/Majority)
Paxos 的根基是“过半原则”:
只有获得超过一半(>N/2) Acceptor 的同意,提议才算通过。 容错能力:N 台节点,可容忍 f 台故障,需 N > 2f 例:5 台 → 可容忍 2 台故障(过半 = 3) 3 台 → 可容忍 1 台故障(过半 = 2)为什么必须过半?任何两个"过半集合"必有交集,所以最多只有一个提议能被多数接受→ 保证一致性。
2.3 Paxos 两阶段流程
Paxos 通过两轮网络交互达成共识:
阶段一:Prepare(准备阶段)
Proposer ──Prepare(编号n)──▶ 所有Acceptor 每个Acceptor: ① 如果n大于它见过的最大编号,承诺"不再接受编号<n的提议" ② 返回它已接受的最高编号的提议(如果有)作用:Proposer 探明当前状态,确保自己的提议编号最高,避免冲突。
阶段二:Accept(接受阶段)
Proposer ──Accept(n, value)──▶ 所有Acceptor 收到多数(过半)Acceptor承诺后 Acceptor接受该提议 → 广播给Learner作用:Proposer 获得多数承诺后,正式提交值,多数接受则达成共识。
2.4 完整例子:3 台节点选值
假设 3 台 Acceptor(A、B、C),要决定一个值:
① Proposer P 发送 Prepare(1) A、B、C 都没见过提议 → 都承诺,返回"无已接受提议" ② P 收到 A、B 的承诺(过半2/3) → 发送 Accept(1, "值X") A、B 接受 "值X" → 过半 → 共识达成 "值X" ✅故障场景:
如果 C 也收到另一个 Proposer 的 Accept(2, "值Y") 但 A、B 已经接受 "值X" → C 会拒绝(因为编号2可能不满足约束) 最终仍是多数接受的 "值X" 获胜2.5 Paxos 总结
| 特点 | 说明 |
|---|---|
| 角色 | Proposer / Acceptor / Learner |
| 核心 | 多数派(过半)原则 |
| 流程 | Prepare(探明)+ Accept(提交)两阶段 |
| 保证 | 只要有足够多节点正常,最终所有节点一致 |
| 局限 | 理论性强、工程实现复杂、难以直接落地 |
一句话:Paxos =编号递增 + 两阶段投票 + 过半决定,多个提案者竞争,最终只有一个值被多数接受。
三、ZAB 协议详解(ZooKeeper 真正用的)
ZAB(ZooKeeper Atomic Broadcast)是 ZooKeeper 的专用共识协议,解决两大问题:Leader 选举+数据原子广播。
3.1 ZAB 的三个阶段(类似 Paxos 但更专注)
① 发现(Discovery) → 选出 Leader ② 同步(Synchronization) → 新 Leader 同步最新数据给所有 Follower ③ 广播(Broadcast) → Leader 接收写请求,广播给 Follower 达成一致3.2 Leader 选举(Fast Leader Election)
ZooKeeper 选主的核心是比较 zxid(ZooKeeper Transaction ID):
选举标准: ① zxid 大的节点优先(数据最新) ② zxid 相同,myid(节点ID) 大的优先 zxid = 64位:(高32位 epoch + 低32位 事务计数)选举过程(举例 3 台:node1、node2、node3):
① node1 启动,投自己 (zxid=0, myid=1) ② node2 启动,投自己 (zxid=0, myid=2) → 2 > 1,node1 改投 node2 ③ node3 启动,投自己 (zxid=0, myid=3) → 3 > 2,node1、node2 都改投 node3 ④ node3 获得 3/3 多数 → 成为 Leader ✅ 如果某节点数据更新(zxid更大),则它优先当选3.3 ZAB 数据同步:为什么 ZooKeeper 数据一致
Leader 当选后: ① Leader 会保证自己数据最新(必要时从其他节点补齐) ② Leader 把事务(写操作)广播给所有 Follower ③ Follower 过半确认 → Leader 提交 → 通知所有 Follower 提交 ④ 客户端读到的数据在各节点是一致的ZAB 保证:Leader 处理写请求 + 过半确认 + 广播提交,所以 ZooKeeper 是CP模型(一致性优先,可用性降级时拒绝写)。
四、Paxos vs ZAB vs Raft 对比
| 维度 | Paxos | ZAB | Raft |
|---|---|---|---|
| 定位 | 理论基石 | ZooKeeper 专用 | 工程化实现 |
| 典型使用 | 学术/基础 | ZooKeeper | Etcd |
| 选主方式 | 两阶段投票 | zxid+myid 比较 | 随机超时+票数 |
| 广播 | 不专注 | 原子广播 | 日志复制 |
| 复杂度 | 高(难懂) | 中 | 低(易懂) |
| 一致性模型 | 共识 | CP | CP |
ZooKeeper 选主其实更贴近"简化的 Paxos 变体 + 原子广播",工程上用了更实用的实现。
五、ZooKeeper 中 Paxos 相关实现细节
ZooKeeper 虽然不用纯 Paxos,但核心思想一致:
- 过半原则:选主和写都需要多数派确认
- 编号递增:zxid 相当于 Paxos 的"编号",越大越新
- 多数确认:写请求需过半 Follower 确认才提交
一句话理解 ZooKeeper 的选举:
ZooKeeper 选 Leader = 所有节点广播自己"谁最新(zxid大)+谁ID大" →多数派同意→ 选出 Leader → Leader 负责所有写 + 原子广播。
六、总结
- Paxos是分布式共识的理论基石:Proposer/Acceptor/Learner 三角色 +Prepare/Accept 两阶段+过半原则
- ZooKeeper 真正用的是 ZAB:选主(zxid+myid比较) + 数据同步 + 原子广播,多数派确认
- Raft是更易实现的工程共识(Etcd 用),Paxos/ZAB/Raft 都保证"多数派一致"
- 理解核心一句话:共识算法 = 编号递增 + 多数派投票 + 只有一个值胜出
面试常考:ZooKeeper 用ZAB而非 Paxos;选主比zxid 大;写需过半确认。