Paxos made simple

111 阅读6分钟

Paxos made simple (2001) & Multi-Paxos

Leslie Lamport. 1998. The part-time parliament. ACM Trans. Comput. Syst. 16, 2 (May 1998), 133–169. doi.org/10.1145/279…

Paxos 的核心是一个共识算法:the "synod" algorithm

  • 一致性的 safety requirements:

    • 只有被提议的值才有可能被选中
    • 只有一个值被选中
    • 处理器不知道一个值已经被选中了,除非它真的被选中了
  • 共识算法中的三种角色可以由三类代理 agents 来执行:

    • proposers
    • acceptors
    • learners

传统的异步的,没有拜占庭故障的模型:

  • 代理以任意速度运行,可能因为停止而失败,并可能重新启动
  • 消息可能需要任意长的时间,可以复制,可能丢失,但它们不会损坏

2.2 Choosing a Value

multiple acceptor agents

【P1.】 An acceptor must accept the first proposal that it receives. (liveness)

存在的问题:如果 proposal 被均匀地 accept 了,就不能选出 majority 的那一个了

an acceptor must be allowed to accept more than one proposal

为每一个 proposal 分配一个自然数编号(不同的),所以每个 proposal 由一个 proposal number 和一个值构成

一个 proposal 的值如果被大部分的 acceptors 接受,那么这个值就被选中

允许选择多个 proposal ,但必须保证所有被选择的 proposal 都具有相同的 value

自然数编号的作用:

由于每个 acceptor 可以接受多个proposal,那么根据 chosen 的定义,就可能存在多个 proposal 被 chosen,系统就失去了 safety

【P2.】 If a proposal with value v is chosen, then every higher-numbered proposal that is chosen has value v. (safety)

satisfy P2 by satisfying:

【P2a .】 If a proposal with value v is chosen, then every higher-numbered proposal accepted by any acceptor has value v.

一个 proposal 要想被 chosen,那么至少先被一个 acceptor 接受。如果在大于 m 的 number 中接受的都是 v,那么就不可能有其它 proposal 被 chosen

由于网络是异步的,可能存在一个 节点c 从未收到任何 proposl,但是系统已经 chosen 了某个 v。假如此时有一个 proposer 提议了另一个 proposal,而节点 c 刚好收到该 proposal,那么根据 P1,节点c 必须接受该 proposal,而这却违反了 P2a.

Maintaining both P1 and P2a requires strengthening P2a to:

【P2b .】 If a proposal with value v is chosen, then every higher-numbered proposal issued by any proposer has value v.

acceptor 只会接受 proposer 提议的值。如果在大于 m 的 view 中提议的都是 tx1,那么就不可能有其它 proposal 被接受

P2bP2aP2P_{2b} \Rightarrow P_{2a} \Rightarrow P_2

how to satisfy P2b

用数学归纳法证明:一个 proposal 的 number 是 m, value 是 v ,并被选中,则对于 number n > m 的所有 proposal 也有 value v。

(1)假设 m .... (n-1) 的 proposal 都有 value v

(2)编号为 m 的 proposal 被选中了,那么一定有一个包含了大部分 acceptors 的集合 C,里面的 acceptors 都 accept 了这个 proposal。由假设(1),每一个 C 中的 acceptor 也 accept 了编号是 m .... (n-1) 的 proposal。因为 C 集合中 acceptor 的数量超过了半数,那么任意一个超过半数的 acceptors 的集合 S 都会存在一个成员 acceptor 也属于 C。

satisfy P2b by maintaining the invariance of P2c

【P2c .】 For any v and n, if a proposal with value v and number n is issued, then there is a set S consisting of a majority of acceptors such that either (a) no acceptor in S has accepted any proposal numbered less than n, or (b) v is the value of the highest-numbered proposal among all proposals numbered less than n accepted by the acceptors in S.

如何满足 P2b: 每个具有更高 number 的 proposal 在被提议时的值就是 v?

我们假设 id=m , value=v 的 proposal 被 chosen,那么至少 majority acceptor accept the proposal with id=m, 令这个 majority acceptor 的集合是 C,要使得 id>m 的 proposal 的 value=v,那么这个新的 proposal 在被提议之前就要询问到 C 中的至少一个节点,然后 propose 从这个节点获取到的值 v

但是 C 中的节点对于其他 proposer 是未知的?令新的 proposal (id=n)被提议前去询问任意 majority 个节点,记这个集合是 S,那么 S 和 C 一定存在交集,即有一个共同的节点

集合 S 要满足下面的条件之一:

  1. S 中的 acceptor 没有 accept 过 number 小于 n 的 proposal

    • id=n 时还没有 accept 过任何 proposal,那么 proposer 就可以提议一个任意的值
  2. S 中的 acceptor accept 的 number 小于 n 的 proposal 中那个 number 最大的 proposal 的值是 v

    • 如果存在已被接受的 proposal,则必须提议的值是 v,同时要求 S 中的 acceptor 不再接收 id<n 的 proposal

[Proposer's algorithm]

proposer 要求 acceptor 不接受编号小于 n 的 proposal

  1. a prepare request with number n:

proposer 选择一个新的编号n,并向某一组 acceptors 中的每个成员发送一个请求 prepare request,要求其回应:

  • 承诺不会接受编号小于 n 的 proposal
  • 如果已经接受过 proposal 的话, 就返回它已接受的编号小于 n 的且编号最大的 proposal
  1. 如果 proposer 收到了来自大多数 acceptor 的请求响应 (对应 P2c 中的集合 S),那么它就可以发布一个编号为n,值为 v 的 proposal,(v 是答复中编号最高的 proposal 的值或者没有建议的话就是 proposer 选择的任何值)

  2. accept request: proposer 向一些 acceptors (不一定是第1步中的那些) 发送一个 请求接收 proposal 的 request

[Acceptor's algorithm]

【P1a .】 An acceptor can accept a proposal numbered n if it has not responded to a prepare request having a number greater than n.

优化:acceptor 只需要记住它曾经接受过的编号最大的proposal和它所答复的编号最大的 prepare request

proposer 总是可以放弃一个 proposal,只要它从不试图发布另一个具有相同编号的 proposal

合并上面两个算法:

【阶段 1】Prepare

(a) proposer 选择一个编号为 n 的 proposal,并将一个编号为 n 的 prepare request 发送给大多数 acceptors。

(b) 如果 acceptor 接收到一个编号为 n 的 prepare request,n 大于它已经回复过的 prepare request, 那么它回复承诺不会 accept 任何编号小于 n 的 proposal,并回复它已经 accept 的编号最大的 proposal

【阶段 2】Accept

(a) 如果 proposer 接收到了来自大部分 acceptors 的对于编号 n 的 prepare request 的响应,它将发送一个 accept request (a proposal numbered n with a value v)给 acceptors,v 是响应中编号最大的 proposal 的值或者没有已接受的proposal的话是任意的值

(b) 如果一个 acceptor 接收到了一个对编号为 n 的 proposal 的 accept request,它将 accept 除非它已经响应过一个编号大于 n 的 prepare request

性能优化:

proposer 可以随时丢弃 proposal

如果一些 proposer 已经开始试图发布一个更高编号的 proposal ,那么就可以放弃一个 proposal

如果一个 acceptor 忽略了一个 prepare 或 accept request,是因为它已经收到了一个有更高编号的prepare request,那么它可能应该通知 proposer 放弃它的 proposal

2.3 Learning a Chosen Value

  • method 1: learner 知道一个 proposal 已经被大部分 acceptor 接受的一种方法是:让所有的 acceptor accept proposal 的时候就响应给所有的 learner 并给它们发送 proposal。如果有 A 个 learner 和 B 个 acceptor 的话,需要 A * B 个 responses。
  • method 2: 令 acceptors 将它们的 acceptances 响应给一个 distinguished learner, 然后这个 distinguished leaner 会通知其他的 learner 选中了哪个 value ( the distinguished learner could fail ---- less reliable), 只需要 A+B 个 responses。
  • method 3: 令 acceptors 将它们的 acceptances 响应给一些 distinguished learners (以更大的通信复杂性为代价)
  • method 4: 令 learner 询问 acceptor 它们接受了哪个 proposal

2.4 Progress

一个死循环的例子:有两个 proposer p,q

  • p 对编号为 n_1 的proposal 完成了【阶段1】
  • q 对编号为 n_2 的proposal 完成了【阶段1】(n_2 > n_1)
  • acceptor 承诺不会 accept 任何编号小于 n_2 的 proposal
  • p 的【阶段2】发出的 accept request 被忽略
  • p 对编号为 n_3 的proposal 完成了【阶段1】(n_3 > n_2)
  • .......

a distinguished proposer must be selected as the only one to try issuing proposals

a reliable algorithm for electing a proposer must use either randomness or real time—for example, by using timeouts (FLP Impossibility)

如果存在多个 proposer 就会一直存在上面的活锁问题,直到只剩下一个 proposer

Paxos 中的 leader 是弱 leader,可能同时存在多个,而 Raft 是强 leader,最多只能同时存在一个

2.5 The Implementation

Paxos algorithm:

  • each process plays the role of proposer, acceptor, and learner

  • chooses a leader plays the roles of the distinguished proposer and the distinguished learner

  • Stable storage, preserved during failures

  • no two proposals are ever issued with the same number

    • 不同的 proposer 从不相交的数字集合中选择编号,所以不会发出相同编号的 proposal

Multi-Paxos

  1. acceptor 的持久化状态
  • lastLogIndex: 这个服务器已经 accept 的 proposal 的最大 entry

  • minProposal: 这个服务器即将 accept 的 proposal 的最小编号(已经收到了 prepare request,但还没收到 accept request 时),若此时还未收到过 prepare request,则 minProposal=0

  • 对于每个 acceptor 存储的 log 中的 log entry i \in [1, lastLogIndex]:

    • acceptedProposal[i]:在这个 log entry 中,服务器最后 accept 的 proposal 的 number 号。若还未 accept 任何 proposal,则 acceptedProposal[i]=0;若 acceptedValue[i] 已经被 chosen,则 acceptedProposal[i]=acceptedProposal[i]=\infin
    • acceptedValue[i]:在这个 log entry 中,服务器最后 accept 的 proposal 的 value。若还未 accept 任何 proposal,则值为 null
  • firstUnchosenIndex: acceptedProposal[i]<acceptedProposal[i] < \infin 的最小的 log index

  1. proposer 的持久化状态
  • maxRound:proposer 见过的最大的 round number
  1. proposer 的 volatile 状态
  • nextIndex:下一个用于 client request 的 entry 的 index
  • prepared:若 prepared=True,则 proposer 就不需要再发起 prepare request (因为此时 majority acceptors 已经响应了 prepare request 且 noMoreAccepted=True),prepared 初始值为 false

multiPaxos1.jpg

Basic-Paxos协议的执行流程针对每条redolog都至少存在三次网络交互的延迟(1. 产生logID;2. prepare阶段;3. accept阶段)

在这三个阶段中,根据Paxos协议的约束,server应答prepare消息和accept消息前都要持久化本地redolog,以避免重启后的行为与重启前自相矛盾,使用Basic-Paxos进行redolog同步的延迟包括了3次网络交互加2次写本地磁盘

leader 乱序提交 log \rightarrow 幽灵复现问题


其他参考资料:

Paxos Summary (Diego Ongaro and John Ousterhout 2013)

从 Paxos 到 Multi-Paxos (一) - 知乎 (zhihu.com)

从 Paxos 到 Multi-Paxos(二) - 知乎 (zhihu.com)

[Paxos三部曲之二] 使用Multi-Paxos协议的日志同步与恢复 | Oceanbase列传