一、核心概念
Paxos 是一种分布式共识算法,由 Leslie Lamport 于 1990 年提出,用于在分布式系统中解决多个节点对某个值达成一致的问题。它是分布式系统理论的基石,Chubby、Zookeeper 等系统都基于 Paxos 或其变种实现。
解决的核心问题
在存在节点故障、网络延迟、消息丢失的分布式环境中,如何保证多个节点最终对某个提案(Proposal)达成一致意见,且一旦达成共识就不可更改。
三种角色
- Proposer(提议者):提出提案(Proposal Number + Value)
- Acceptor(接受者):投票决定是否接受提案(通常是过半数集群)
- Learner(学习者):学习已被选定的提案值
注:实际系统中,同一个节点可以同时扮演多种角色。
二、Paxos 工作流程(Basic Paxos)
Paxos 协议分为 两个阶段:Prepare 阶段和 Accept 阶段。
阶段一:Prepare(准备阶段)
目标:探测当前已被接受的最大提案号,占位并获取投票权
- Proposer 行为:
- 生成全局唯一且递增的提案编号
N - 向多数 Acceptor 发送
Prepare(N)请求
- 生成全局唯一且递增的提案编号
- Acceptor 行为:
- 收到
Prepare(N)后,检查自己的状态:- 如果
N大于 自己承诺的所有提案号maxN,则:- 承诺不再接受编号 小于 N 的提案
- 返回
Promise(N, acceptedN, acceptedValue)acceptedN:已接受的最大提案号acceptedValue:对应的提案值
- 如果
N小于或等于maxN,则拒绝并返回maxN
- 如果
- 收到
流程示意:
Proposer Acceptor1 Acceptor2 Acceptor3
| | | |
|---Prepare(N=5)---------->| | |
| | | |
|---Prepare(N=5)---------------------->| |
| | | |
|---Prepare(N=5)------------------------------------->|
| | | |
|<--Promise(5, null)-------| | |
|<--Promise(5, 3, "A")---------------- | |
|<--Promise(5, 4, "B")----------------------- |
阶段二:Accept(接受阶段)
目标:提交提案值,让多数 Acceptor 接受
- Proposer 行为:
- 如果收到多数 Acceptor 的
Promise响应:- 若所有响应中
acceptedValue都为空,则可以提交自己的值V - 若存在
acceptedValue,则必须提交acceptedN最大的那个值(保证一致性)
- 若所有响应中
- 向多数 Acceptor 发送
Accept(N, V)请求
- 如果收到多数 Acceptor 的
- Acceptor 行为:
- 收到
Accept(N, V)后:- 如果
N >= maxN(承诺的最小提案号):- 接受该提案,更新
acceptedN = N, acceptedValue = V - 返回
Accepted(N, V)
- 接受该提案,更新
- 否则拒绝
- 如果
- 收到
- Learner 行为:
- 当 Learner 收到多数 Acceptor 的
Accepted(N, V)后,确认值V已被选定
- 当 Learner 收到多数 Acceptor 的
流程示意:
Proposer Acceptor1 Acceptor2 Acceptor3
| | | |
|---Accept(5, "B")-------->| | |
|---Accept(5, "B")-------------------->| |
|---Accept(5, "B")------------------------------------->|
| | | |
|<--Accepted(5, "B")-------| | |
|<--Accepted(5, "B")------------------ | |
|<--Accepted(5, "B")------------------------------ |
| | | |
(值 "B" 达成共识)
三、关键原理与保证
1. 提案编号的唯一性与递增性
- 提案号
N通常使用 时间戳 + Server ID 组合生成,确保全局唯一且递增 - 示例:
N = timestamp * 1000 + serverId
2. 多数派原则(Quorum)
- 过半数(Majority) 是共识的关键:任意两个多数派集合必有交集
- 例如 5 个节点,至少需要 3 个节点同意
- 保证了新提案一定能看到已被接受的旧提案
3. 为什么要选择 acceptedN 最大的值?
场景:Prepare 阶段收到多个 Acceptor 返回的已接受提案
- 编号最大的提案最有可能已经被多数派接受
- 选择它可以避免破坏已达成的共识(一致性保证)
示例:
Acceptor1: Promise(10, acceptedN=5, acceptedValue="A")
Acceptor2: Promise(10, acceptedN=8, acceptedValue="B")
Acceptor3: Promise(10, null)
→ Proposer 必须选择 "B"(acceptedN=8 最大)
四、活锁问题与 Multi-Paxos 优化
Basic Paxos 的活锁问题
场景:多个 Proposer 并发提案,互相覆盖对方的 Prepare 请求
时间线:
T1: Proposer1 发送 Prepare(N=5)
T2: Proposer2 发送 Prepare(N=6) [覆盖 N=5]
T3: Proposer1 发现被拒绝,发送 Prepare(N=7) [覆盖 N=6]
T4: Proposer2 发现被拒绝,发送 Prepare(N=8) [覆盖 N=7]
... (无法达成共识)
解决方案:
- 随机退避:提案失败后随机等待一段时间再重试
- Leader 选举:引入 Multi-Paxos,选举唯一 Leader 负责提案
Multi-Paxos(生产环境常用)
核心改进:
- 选举 Leader:只有 Leader 可以提议,避免冲突
- 省略 Prepare 阶段:Leader 稳定后,后续提案直接进入 Accept 阶段
- 连续决策:将多个值的共识变为日志序列的共识(如 Zookeeper 的 ZAB 协议)
简化流程:
Leader 当选后:
1. 初始时执行一次完整 Paxos(确立 Leader 身份)
2. 后续提案直接发送 Accept(N, V) 给 Acceptors
3. Acceptors 无需再执行 Prepare 判断,直接接受
五、应用场景
1. Zookeeper(ZAB 协议)
- ZAB(Zookeeper Atomic Broadcast)是 Paxos 的工程化实现
- 保证事务请求的全局顺序一致性
2. Chubby(Google 分布式锁服务)
- 使用 Paxos 选举 Master 节点
- 提供分布式锁和配置中心功能
3. 分布式数据库
- TiDB:使用 Raft(Paxos 的简化版)实现多副本一致性
- CockroachDB:基于 Raft 的分布式事务
六、答题总结
Paxos 协议 通过 两阶段提交 解决分布式共识问题:
- Prepare 阶段:
- Proposer 发送编号
N,Acceptor 承诺不接受更小的编号 - 返回已接受的最大提案(若有)
- Proposer 发送编号
- Accept 阶段:
- Proposer 提交值(必须选择 acceptedN 最大的值)
- Acceptor 接受并通知 Learner
关键要点:
- 多数派原则保证任意两次投票必有交集
- 提案号递增避免旧提案覆盖新共识
- 活锁问题通过 Multi-Paxos 或 Leader 选举解决
面试加分项:
- 对比 Raft 算法(Raft 更易理解,工程实现更友好)
- 说明 Zookeeper 的 ZAB 与 Paxos 的关系
- 提到 Paxos Made Simple 论文的经典地位
口述建议:先讲两阶段流程,再解释多数派和提案号作用,最后补充 Multi-Paxos 优化,逻辑清晰更易理解。