Paxos 算法推导过程

1、prepare

(a) Proposer 选择一个提案编号N,然后向半数以上的 Acceptor 发送编号为N的Prepare请求。

(b)如果一个 Acceptor 收到一个编号为N 的Prepare请求,且N大于该 Accpetor 已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号是最大的提案(如果有的话)作为响应反馈给 Proposer ,同时该 Accpetor 承诺不再接受任何编号小于N的提案。

2、accept

(a)如果Proposer收到半数以上 Accpetor 对其发出的编号为N的Prepare请求的回应,那么它就会发送一个针对【N,V】提案的Accpetor请求给半数以上的 Accpetor 。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由 Proposer 自己决定。

(b)如果 Accpetor 收到一个针对编号为N的提案的 Accpetor 请求,只要该 Accpetor 没有对编号大于N的 Prepare 请求做出过响应,它就接受该提案。

备注:当然实际运行过程中,每一个 Proposer 都有可能产生多个提案,但只要每个 Proposer 都遵循如上述的算法运行,就一定能够保证算法执行的正确性。acceptor返回给proposer,要么是 null,要么是 value 值,要么忽略不传。

会产生一个问题:如何保证算法的活性?

假设有两个 Proposer 依次提出编号递增的提案,最终会陷入死循环,没有value被选定。(无法保证活性)。

步骤一:Proposer P1 发出编号为M1的 Prepare 请求,收到过半响应。完成了阶段一的流程。

步骤二:同时,Proposer P2 发出编号为M2(M2 > M1)的Prepare请求,也收到过半响应,也完成了阶段一的流程。于是Accpetor承诺不再接受编号小于M2的提案。

步骤三:P1进入第二阶段的时候,发出的 Accpetor 请求被 Accpetor 忽略,于是P1再次进入阶段一并发出编号为M3(M3 > M2)的Prepare请求。

步骤四:这又导致P2在阶段二的Accpetor请求被忽略。P2再次进入阶段一,发出编号为M4(M4>M3)的Prepare请求。。。

陷入死循环,都无法完成阶段二,没有value被选定。

解决方案:通过选取主 Proposer,并规定只有主 Proposer 才能提出议案。这样一来只要主 Proposer 和过半的 Accpetor 能够正常进行网络通信,那么但凡主 Proposer 提出一个编号更高的提案,该提案就会被批准,这样通过选择一个主 Proposer,整套 Paxos 算法就能够保持活性。

你可能感兴趣的:(Zookeeper,java)