Paxos算法
Paxos中 proposer 和 acceptor 是算法的核心角色,paxos 描述的就是在一个由多个 proposer 和多个 acceptor 构成的系统中,如何让多个 acceptor 针对 proposer 提出的多种提案达成一致的过程,而 learner 只是“学习”最终被批准的提案。
Paxos协议流程还需要满足几个约束条件:
- Acceptor必须接受它收到的第一个提案;
- 如果一个提案的v值被大多数Acceptor接受过,那后续的所有被接受的提案中也必须包含v值(v值可以理解为提案的内容,提案由一个或多个v和提案编号组成);
- 如果某一轮 Paxos 协议批准了某个 value,则以后各轮 Paxos 只能批准这个value;
paxos算法的两个阶段4个过程:
Phase 1 a) proposer向网络内超过半数的acceptor发送prepare消息 b) acceptor正常情况下回复promise消息 Phase 2 a) 在有足够多acceptor回复promise消息时,proposer发送accept消息 b) 正常情况下acceptor回复accepted消息
Phase 1 准备阶段
Proposer 生成全局唯一且递增的ProposalID,向 Paxos 集群的所有机器发送 Prepare请求,这里不携带value,只携带N即ProposalID 。
Acceptor 收到 Prepare请求 后,判断:收到的ProposalID 是否比之前已响应的所有提案的N大: 如果是,则: (1) 在本地持久化 N,可记为Max_N。 (2) 回复请求,并带上已Accept的提案中N最大的value(若此时还没有已Accept的提案,则返回value为空)。 (3) 做出承诺:不会Accept任何小于Max_N的提案。
如果否:不回复或者回复Error。
Phase 2 选举阶段
P2a:Proposer 发送 Accept 经过一段时间后,Proposer 收集到一些 Prepare 回复,有下列几种情况: (1) 回复数量 > 一半的Acceptor数量,且所有的回复的value都为空,则Porposer发出accept请求,并带上自己指定的value。 (2) 回复数量 > 一半的Acceptor数量,且有的回复value不为空,则Porposer发出accept请求,并带上回复中ProposalID最大的value(作为自己的提案内容)。 (3) 回复数量 <= 一半的Acceptor数量,则尝试更新生成更大的ProposalID,再转P1a执行。
P2b:Acceptor 应答 Accept Accpetor 收到 Accpet请求 后,判断: (1) 收到的N >= Max_N (一般情况下是 等于),则回复提交成功,并持久化N和value。 (2) 收到的N < Max_N,则不回复或者回复提交失败。
P2c: Proposer 统计投票 经过一段时间后,Proposer 收集到一些 Accept 回复提交成功,有几种情况: (1) 回复数量 > 一半的Acceptor数量,则表示提交value成功。此时,可以发一个广播给所有Proposer、Learner,通知它们已commit的value。 (2) 回复数量 <= 一半的Acceptor数量,则 尝试 更新生成更大的 ProposalID,再转P1a执行。 (3) 收到一条提交失败的回复,则尝试更新生成更大的 ProposalID,再转P1a执行。
用于达成共识性问题,即对多个节点产生的值,该算法能保证只选出唯一一个值。
主要有三类节点:
- 提议者(Proposer):提议一个值;
- 接受者(Acceptor):对每个提议进行投票;
- 告知者(Learner):被告知投票的结果,不参与投票过程。

执行过程
规定一个提议包含两个字段:[n, v],其中 n 为序号(具有唯一性),v 为提议值。
1. Prepare 阶段
下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程,每个 Proposer 都会向所有 Acceptor 发送 Prepare 请求。

当 Acceptor 接收到一个 Prepare 请求,包含的提议为 [n1, v1],并且之前还未接收过 Prepare 请求,那么发送一个 Prepare 响应,设置当前接收到的提议为 [n1, v1],并且保证以后不会再接受序号小于 n1 的提议。
如下图,Acceptor X 在收到 [n=2, v=8] 的 Prepare 请求时,由于之前没有接收过提议,因此就发送一个 [no previous] 的 Prepare 响应,设置当前接收到的提议为 [n=2, v=8],并且保证以后不会再接受序号小于 2 的提议。其它的 Acceptor 类似。

如果 Acceptor 接收到一个 Prepare 请求,包含的提议为 [n2, v2],并且之前已经接收过提议 [n1, v1]。如果 n1 > n2,那么就丢弃该提议请求;否则,发送 Prepare 响应,该 Prepare 响应包含之前已经接收过的提议 [n1, v1],设置当前接收到的提议为 [n2, v2],并且保证以后不会再接受序号小于 n2 的提议。
如下图,Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的 Prepare 请求,由于之前已经接收过 [n=4, v=5] 的提议,并且 n > 2,因此就抛弃该提议请求;Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的 Prepare 请求,因为之前接收到的提议为 [n=2, v=8],并且 2 <= 4,因此就发送 [n=2, v=8] 的 Prepare 响应,设置当前接收到的提议为 [n=4, v=5],并且保证以后不会再接受序号小于 4 的提议。Acceptor Y 类似。

2. Accept 阶段
当一个 Proposer 接收到超过一半 Acceptor 的 Prepare 响应时,就可以发送 Accept 请求。
Proposer A 接收到两个 Prepare 响应之后,就发送 [n=2, v=8] Accept 请求。该 Accept 请求会被所有 Acceptor 丢弃,因为此时所有 Acceptor 都保证不接受序号小于 4 的提议。
Proposer B 过后也收到了两个 Prepare 响应,因此也开始发送 Accept 请求。需要注意的是,Accept 请求的 v 需要取它收到的最大提议编号对应的 v 值,也就是 8。因此它发送 [n=4, v=8] 的 Accept 请求。

3. Learn 阶段
Acceptor 接收到 Accept 请求时,如果序号大于等于该 Acceptor 承诺的最小序号,那么就发送 Learn 提议给所有的 Learner。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那么该提议的提议值就被 Paxos 选择出来。

约束条件
1. 正确性
指只有一个提议值会生效。
因为 Paxos 协议要求每个生效的提议被多数 Acceptor 接收,并且 Acceptor 不会接受两个不同的提议,因此可以保证正确性。
2. 可终止性
指最后总会有一个提议生效。
Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性。