Paxos协议流程
Paxos 协议是分布式系统中实现 “一致性” 的经典算法,核心目标是让多个节点在存在故障(如节点崩溃、网络延迟 / 分区)的情况下,对某个 “提案”(如数据值、操作指令)达成一致结论。它的设计复杂但逻辑严谨,是后续 ZAB、Raft 等协议的思想源头。
一、Paxos 的核心角色
Paxos 协议通过划分三种角色,将 “提案提出 - 投票 - 确认” 的流程解耦,所有节点可根据场景扮演不同角色(一个节点可同时扮演多个角色):
- Proposer(提案者):发起提案(如提出 “将数据设为 10”),负责将提案分发给 Acceptor 并争取支持。
- Acceptor(接受者):对提案进行投票(同意 / 拒绝),只有获得多数 Acceptor 同意的提案,才能被最终确认。
- Learner(学习者):不参与投票,仅同步 “已确认的提案”,确保所有节点最终获取一致结果(如从 Acceptor 或 Proposer 处获取确认后的提案)。
二、Paxos 的核心流程:两阶段提交
Paxos 通过 “Prepare(准备)阶段” 和 “Accept(接受)阶段”,确保即使存在多个 Proposer 同时提案,最终也只会有一个提案被多数 Acceptor 确认,避免 “多个提案同时通过” 的一致性问题。
1. 第一阶段:Prepare 阶段(争取提案 “优先级”)
Proposer 发起提案前,先通过 Prepare 阶段确认 “自己的提案是否有资格被投票”,避免后续投票冲突:
- Proposer 生成提案编号:每个提案必须有一个全局唯一且递增的编号(如 “节点 ID + 时间戳”),编号越大,提案优先级越高。
- Proposer 发送 Prepare 请求:向多数 Acceptor(超过集群节点数的 1/2,如 3 节点需 2 个,5 节点需 3 个)发送 Prepare 请求,携带提案编号(仅编号,暂不携带提案内容)。
- Acceptor 处理 Prepare 请求:
- Acceptor 维护两个状态:
max_proposal_id(已响应的最大提案编号)、accepted_proposal(已接受的提案,含编号和内容)。 - 若收到的提案编号 >
max_proposal_id:更新max_proposal_id为当前编号,回复 Proposer “同意准备”,并附带自己已接受的提案(若有); - 若收到的提案编号 ≤
max_proposal_id:拒绝该请求(因已有更高优先级的提案在处理)。
- Acceptor 维护两个状态:
- Proposer 判断是否进入下一阶段:若收到多数 Acceptor 的 “同意准备” 回复,则进入 Accept 阶段;否则,等待一段时间后生成更大的提案编号,重新发起 Prepare 请求。
2. 第二阶段:Accept 阶段(确认提案)
Proposer 获得多数 Acceptor 的 “准备同意” 后,正式发起提案内容,争取最终确认:
- Proposer 确定提案内容:
- 若 Prepare 阶段的回复中,有 Acceptor 已接受过其他提案(附带了
accepted_proposal),则 Proposer 必须放弃自己原有的提案内容,改用 “已接受提案中编号最大的内容”(确保后续提案与已有接受结果兼容); - 若所有回复均无已接受提案,则 Proposer 可使用自己最初想提出的内容。
- 若 Prepare 阶段的回复中,有 Acceptor 已接受过其他提案(附带了
- Proposer 发送 Accept 请求:向所有参与 Prepare 阶段并同意的 Acceptor,发送 Accept 请求,携带 “最终提案(编号 + 内容)”。
- Acceptor 处理 Accept 请求:
- 若收到的提案编号 == 自己的
max_proposal_id(即没有更高优先级的提案插入):接受该提案,更新accepted_proposal为当前提案,回复 Proposer “同意接受”; - 若收到的提案编号 <
max_proposal_id(有更高优先级的提案已响应):拒绝该请求。
- 若收到的提案编号 == 自己的
- Proposer 确认提案并通知 Learner:
- 若收到多数 Acceptor 的 “同意接受” 回复:提案被 “最终确认”,Proposer 向所有 Learner 发送 “已确认提案”,让所有节点同步结果;
- 若未收到多数同意:回到 Prepare 阶段,生成更大的提案编号,重新发起流程。
三、Paxos 的关键特性:为何能保证一致性?
- 多数派原则:无论是 Prepare 阶段还是 Accept 阶段,都要求 “多数 Acceptor 响应”,确保即使部分节点故障,仍能推进流程;同时,“多数” 的交集特性(如 5 节点中,两个多数集至少有 1 个公共节点),避免多个提案同时被确认。
- 提案编号唯一性与递增性:编号唯一确保提案不重复,递增性确保 “后发起的提案优先级更高”,避免旧提案干扰新提案。
- 提案内容兼容性:Prepare 阶段若发现已有接受的提案,Proposer 必须沿用 “最大编号的已接受内容”,确保后续提案与已有结果一致,避免 “新提案覆盖旧接受结果”。
四、Paxos 的局限性(为何后续有 ZAB/Raft)
Paxos 虽逻辑严谨,但存在两个核心问题,导致工业界落地难度大:
- 复杂度高:角色可重叠、流程存在 “重新发起” 的循环,且未明确 “Leader 角色”(多个 Proposer 同时提案时,会频繁触发 Prepare 阶段,效率低);
- 未定义 “恢复机制”:若 Proposer 或 Acceptor 故障后恢复,如何同步已有状态(如已接受的提案),协议未给出具体方案。
后续的 ZAB(为 ZooKeeper 定制)、Raft(通用简化)协议,本质是在 Paxos 基础上,通过 “固定 Leader 角色”“简化流程”“明确恢复机制”,降低落地难度,适配具体业务场景。
总结
Paxos 是分布式一致性的 “理论基石”,核心是通过 “两阶段提交 + 多数派确认 + 唯一提案编号”,确保故障场景下的一致性。它的思想虽复杂,但后续协议(ZAB/Raft)均基于其核心逻辑优化,理解 Paxos 是掌握分布式一致性的关键。
