2 分布式系统原理
2.8 Paxos 协议
2.8.3 实例
理解Paxos 协议的最直观的方法就是考察几个协议运行的实例。本文给出几个典型的场景下协 议运行的例子。
2.8.3.1 基本例子
基本例子里有5 个 Acceptor,1 个 Proposer,不存在任何网络、宕机异常。我们着重考察各个 Accpetor 上变量 B 和变量 V 的变化,及 Proposer 上变量 b 的变化。
1. 初始状态
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 0 0 0 0 0
V NULL NULL NULL NULL NULL
Proposer 1 b 1
2. Proposer 向所有 Accpetor 发送“Prepare(1)”,所有 Acceptor 正确处理,并回复 Promise(1, NULL) Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 1 1 1 1 1
V NULL NULL NULL NULL NULL
Proposer 1 b 1
3. Proposer 收到 5 个 Promise(1, NULL),满足多余半数的 Promise 的 value 为空,此时发送 Accept(1, v1),其中 v1是Proposer 选择的 Value。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 1 1 1 1 1
V v1 v1 v1 v1 v1
4. 此时,v1被超过半数的Acceptor 批准,v1即是本次Paxos 协议实例批准的 Value。如果 Learner 学习value,学到的只能是 v1
2.8.3.2 批准的 Value 无法改变
在同一个Paxos 实例中,批准的 Value 是无法改变的,即使后续 Proposer 以更高的序号发起 Paxos 协议也无法改变value。
1. 例如,某次 Paxos 协议运行后,Acceptor 的状态是:
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 3 3 3 2 2
V v1 v1 v1 NULL NULL
5 个 Acceptor 中,有 3 个已经在第三轮 Paxos 协议批准了 v1作为value。其他两个 Acceptor 的 V 为空,这可能是因为Proposer 与这两个 Acceptor 的网络中断或者这两个 Acceptor 宕机造成的。
2. 此时,即使有新的 Proposer 发起协议,也无法改变结果。假设 Proposer 发送“prepare(4)消 息”,由于4 大于所有的 Accpetor 的 B 值,所有收到 prepare 消息的 Acceptor 回复 promise 消息。但 前三个Acceptor 只能回复 promise(4, v1_3),后两个 Acceptor 回复 promise(4, NULL)。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 4 4 4 4 4
V v1 v1 v1 NULL NULL
3. 此时,Proposer 可能收到若干个 Acceptor 发送的 promise 消息,没有收到的 promise 消息可 能是网络异常造成的。无论如何,Proposer 要收到至少 3 个 Acceptor 的 promise 消息后才满足协议 中大于半数的约束,才能发送accpet 消息。这 3 个 promise 消息中,至少有 1 个消息是 promise(4, v1_3),
至多3 个消息都是 promise(4,v1_3)。另一方面,Proposer 始终不可能收到 3 个 promise(4, NULL)消 息,最多收到2 个。综上,按协议流程,Proposer 发送的 accept 消息只能是“accept(4, v1)”而不能自 由选择value。
无论这个accept 消息是否被各个 Acceptor 接收到,都无法改变 v1是被批准的value 这一事实。
即从全局看,有且只有 v1是满足超过多数Acceptor 批准的 value。例如,假设 accept(4, v1)消息被 Acceptor 1、Acceptor2、Acceptor4 收到,那么状态变为:
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 4 4 4 4 4
V v1 v1 v1 v1 NULL
从这个例子我们可以看到一旦一个value 被批准,此后永远只能批准这个 value。
2.8.3.3 一种不可能出现的状态
Paxos 协议的核心就在与“批准的 value 无法改变”,这也是整个协议正确性的基础,为了更好 的理解后续对Paxos 协议的证明。这里再看一种看似可能,实际违反协议的状态,这种状态也是后 续反证法证明协议时的一种错误状态。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 1 1 1 2 2
V v1 v1 v1 v2 v2
上述状态中,3 个轮次为 1 的 Acceptor 的 value 为 v1,2 个轮次更高的 Acceptor 的 value 为 v1。 此时被批准的value 是 v1。
假设此时发生新的一轮b=3 的 Paxos 过程,Proposer 有可能收到 Acceptor 3、4、5 发出的 3 个 promise 消息分别为“promise(1, v1_1)”,“promise(2, v2_2)” “promise(2, v2_2)”。按协议,proposer 选择value 编号最大的 promise 消息,即 v2_2 的 promise 消息,发送消息“Accept(3, v2)”,从而使得 最终的批准的value 成为 v2。就使得批准的value 从 v1变成了v2。
上述假设看似正确,其实不可能发生。这是因为本节中给出的初始状态就是不可能出现的。这 是因为,要到达成上述状态,发起prepare(2)消息的 proposer 一定成功的向 Acceptor 4、Acceptor 5 发送了accept(2, v2)。但发送 accept(2, v2)的前提只能是 proposer 收到了 3 个“promise(2, NULL)”消 息。 然而,从状态我们知道,在 b=1 的那轮 Paxos 协议里,已经有 3 个 Acceptor 批准了 v1,这 3 个 Acceptor 在 b=2 时发出的消息只能是 promise(2,v1_1),从而造成 proposer 不可能收到 3 个“promise(2, NULL)”,至多只能收到 2 个“promise(2, NULL)”。另外,只要 proposer 收到一个“promise(2,v1_1)”,
其发送的accept 消息只能是 accept(2, v1)。
从这个例子我们看到Prepare 流程中的第 3 步是协议中最为关键的一步,它的存在严格约束了
“批准的value 无法改变”这一事实。在后续协议推导中我们将看到这一步是如何被设计出来的。
2.8.3.4 节点异常
这里给一个较为复杂的异常状态下Paxos 运行实例。本例子中有 5 个 Acceptor 和 2 个 Proposer。
1. Proposer 1 发起第一轮 Paxos 协议,然而由于异常,只有 2 个 Acceptor 收到了 prepare(1)消息。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 1 1 0 0 0
V NULL NULL NULL NULL NULL
2. Proposer 1 只收到 2 个 promise 消息,无法发起 accept 消息;此时,Proposer 2 发起第二轮 Paxos 协议,由于异常,只有Acceptor 1、3、4 处理了 prepare 消息,并发送 promise(2, NULL)消息
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 2 1 2 2 0
V NULL NULL NULL NULL NULL
3. Proposer 2 收到了 Acceptor 1、3、4 的 promise(2, NULL) 消息,满足协议超过半数的要求,
选择了value 为 v1,广播了 accept(2, v1)的消息。由于异常,只有 Accptor 3、4 处理了这个消息。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 2 1 2 2 0
V NULL NULL v1 v1 NULL
4. Proposer 1 以 b=3 发起新一轮的 Paxos 协议,由于异常,只有 Acceptor 1、2、3、5 处理了 prepare(3) 消息。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 3 3 3 2 3 V NULL NULL v1 v1 NULL
5. 由于异常,Proposer 1 只收到 Acceptor1、2、5 的 promise(3, NULL)的消息,符合协议要求,
Proposer 1 选择 value 为 v2,广播 accept(3, v2)消息。由于异常,这个消息只被 Acceptor 1、2 处理。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 3 3 3 2 3
V v2 v2 v1 v1 NULL
当目前为止,没有任何value 被超过半数的 Acceptor 批准,所以 Paxos 协议尚没有批准任何 value。
然而由于没有3 个 NULL 的 Acceptor,此时能被批准的 value 只能是 v1或者v2其中之一。
6. 此时 Proposer 1 以 b=4 发起新的一轮 Paxos 协议,所有的 Acceptor 都处理了 prepare(4)消息。
Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 4 4 4 4 4
V v2 v2 v1 v1 NULL
7. 由于异常,Proposer 1 只收到了 Acceptor3 的 promise(4, v1_3)消息、Acceptor4 的 promise(4, v1_2)、Acceptor5 的 promise(4, NULL)消息,按协议要求,只能广播 accept(4, v1)消息。假设 Acceptor2、
3、4 收到了 accept(4, v1)消息。由于批准 v1的Acceptor 超过半数,最终批准的 value 为 v1。 Acceptor 1 Acceptor 2 Acceptor 3 Acceptor 4 Acceptor 5
B 4 4 4 4 4
V v2 v1 v1 v1 NULL