并行与分布式系统中的分布式共识算法:Paxos算法与Multi-Paxos算法的区别与实现
字数 2730 2025-12-24 09:31:50
并行与分布式系统中的分布式共识算法:Paxos算法与Multi-Paxos算法的区别与实现
1. 题目描述
在分布式系统中,多个节点(进程)需要对某个值(例如,数据库的一条操作日志、一个配置项)达成一致,这就是共识问题。Paxos算法是解决分布式共识的经典算法,但其基本形式一次只能对一个值达成一致。在实际应用中,我们通常需要一系列值的顺序一致性,这便引出了Multi-Paxos。本题将深入探讨:
- 经典Paxos算法 的基本原理与局限性。
- Multi-Paxos 如何对Paxos进行优化,使其能够高效地对一系列值(一个状态机复制日志)达成共识。
2. 预备知识:问题模型
- 系统模型:异步分布式系统,节点可能故障(崩溃故障,非拜占庭),消息可能丢失、重复、延迟,但不会被篡改。
- 共识目标:多个提议者(Proposers)提出值,希望所有正确的接受者(Acceptors)最终能选定(Chosen)同一个值,且被学习者(Learners)学习。
- 安全性:永远不能选定两个不同的值。
- 活性:只要有足够的正确进程且网络不会永久性分区,最终能选定一个值。
3. 解题过程:经典Paxos算法详解
经典Paxos分为两个主要阶段,旨在解决单个值(称为“实例”或“槽位”)的共识。
阶段一:准备阶段
- 目标:提议者为自己争取一个提案的“许可证”,并了解系统之前是否已接受过其他值。
- 步骤:
- 提议者生成一个全局唯一且单调递增的提案编号
n。 - 提议者向所有接受者发送
Prepare(n)消息。 - 接受者收到
Prepare(n)后:- 如果这是它收到的最大提案编号,它就向提议者回复一个
Promise(n, v)消息,并承诺不再接受编号小于n的提案。其中v是它之前已接受的提案中编号最大的那个提案的值(如果从未接受过,则为空)。 - 如果它之前已回复过更大编号的承诺,则忽略此请求。
- 如果这是它收到的最大提案编号,它就向提议者回复一个
- 提议者生成一个全局唯一且单调递增的提案编号
- 结果:提议者如果收到多数派接受者的承诺,就获得了提案权。
阶段二:接受阶段
- 目标:提议者尝试让多数派接受自己提出的值。
- 步骤:
- 提议者检查收到的所有
Promise回复。如果所有回复中v都为空,它可以使用自己希望提议的值。关键点:如果有一个或多个回复包含了之前被接受的值(v非空),则提议者必须使用这些值中编号最大的那个值作为自己本次提案的值。这保证了算法的安全性。 - 提议者向所有接受者发送
Accept(n, v)消息。 - 接受者收到
Accept(n, v)后,检查提案编号n是否不小于它曾承诺过的最小提案编号。如果是,则接受这个提案,并回复一个Accepted(n, v)消息。
- 提议者检查收到的所有
- 达成共识:一旦某个值被多数派的接受者接受,这个值就被“选定”(Chosen)。学习者(可以是所有进程)通过监听
Accepted消息来学习这个被选定的值。
局限性:每次共识一个值都需要两轮网络通信(Prepare 和 Accept)。对于需要连续达成多个值共识(如复制日志)的场景,效率较低。
4. 解题深化:从Paxos到Multi-Paxos
Multi-Paxos 不是一个新算法,而是对 Paxos 的工程化应用模式。其核心思想是:选举一个稳定的领导者(Leader),来运行一系列Paxos实例,从而大幅减少通信开销。
步骤一:领导者选举(隐式或显式)
- 在Multi-Paxos中,我们期望有一个节点能长时间充当“唯一的提议者”。
- 这可以通过让一个节点运行一次Paxos(比如对“谁是领导者”这个值达成共识)来实现。更常见的是,任何节点都可以通过向所有接受者发送
Prepare请求来尝试成为领导者,谁获得了多数派的承诺,谁就在一段时间内被视为领导者。
步骤二:减少“准备阶段”
- 这是Multi-Paxos的关键优化。一旦一个领导者被稳定确立,它可以认为自己在多个连续的Paxos实例中都拥有“许可证”。
- 因此,对于一系列要提议的值(
v1, v2, v3...),领导者可以:- 只在开始时执行一次准备阶段(发送一轮
Prepare消息),获得一个足够高的提案编号n和对未来一系列实例的承诺。 - 对于后续的每个实例(日志槽位
i),领导者直接进入接受阶段,发送Accept(n, i, v_i)消息。提案编号n在所有实例中保持不变。
- 只在开始时执行一次准备阶段(发送一轮
- 为什么可以这样?因为
Prepare阶段的目的是防止旧提案干扰。一个稳定的领导者,在它领导期间,不会有其他节点用更高的编号来发起提案(假设故障较少),因此一次性的准备就足够了。
步骤三:运行多个Paxos实例
- 每个日志位置对应一个独立的Paxos实例。领导者为每个位置顺序分配一个值,并使用相同的提案编号
n来运行接受阶段。 - 接受者需要为每个实例(
i)分别记录其承诺和接受的状态。当收到Accept(n, i, v)时,它检查实例i的状态,如果其承诺的编号不高于n,则接受。
步骤四:处理间隙与故障恢复
- 网络延迟或节点故障可能导致某些实例的共识被跳过(形成空洞)。学习者(或新的领导者)在发现空洞时,需要运行一次完整的Paxos协议(两阶段)来填补这个空洞,确定该位置的值(通常是“无操作”命令)。
5. 对比总结
| 特性 | Paxos (Basic) | Multi-Paxos |
|---|---|---|
| 目标 | 就单个值达成共识 | 就一系列有序的值(日志)达成共识 |
| 通信轮数 | 每个值需要2轮 (Prepare + Accept) | 稳定领导期间,后续每个值只需1轮 (Accept) |
| 领导者角色 | 无稳定领导者,任何节点可提议 | 有稳定领导者,作为唯一提议者 |
| 提案编号 | 每个提议生成新的、更大的编号 | 领导者使用一个固定的高编号进行一系列提议 |
| 典型应用 | 一次性配置决策、主节点选举 | 状态机复制(如Chubby、Raft的基础)、日志复制 |
结论:Multi-Paxos通过引入稳定的领导者并重用“准备阶段”的承诺,将Paxos从“每次共识成本高昂”优化为“高效连续的日志复制协议”,是构建高可用、强一致分布式存储系统(如分布式数据库、协调服务)的核心理论基石。Raft算法可看作是对Multi-Paxos思想的一种更具体、更易于理解和实现的设计。