Paxos算法原理与推导( 三 )


只要满足P2c即可:

P2c:对于任意的N和V,如果提案[N, V]被提出,那么存在一个半数以上的Acceptor组成的集合S,满足以下两个条件中的任意一个:
  • S中每个Acceptor都没有接受过编号小于N的提案 。
  • S中Acceptor接受过的最大编号的提案的value为V 。
Proposer生成提案
为了满足P2b,这里有个比较重要的思想:Proposer生成提案之前,应该先去『学习』已经被选定或者可能被选定的value,然后以该value作为自己提出的提案的value 。如果没有value被选定,Proposer才可以自己决定value的值 。这样才能达成一致 。这个学习的阶段是通过一个『Prepare请求』实现的 。
于是我们得到了如下的提案生成算法:
  1. Proposer选择一个新的提案编号N,然后向某个Acceptor集合(半数以上)发送请求,要求该集合中的每个Acceptor做出如下响应(response) 。
(a) 向Proposer承诺保证不再接受任何编号小于N的提案 。
(b) 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案 。
我们将该请求称为编号为N的Prepare请求 。
  1. 如果Proposer收到了半数以上的Acceptor的响应,那么它就可以生成编号为N,Value为V的提案[N,V] 。这里的V是所有的响应中编号最大的提案的Value 。如果所有的响应中都没有提案,那 么此时V就可以由Proposer自己选择 。
  2. 生成提案后,Proposer将该提案发送给半数以上的Acceptor集合,并期望这些Acceptor能接受该提案 。我们称该请求为Accept请求 。(注意:此时接受Accept请求的Acceptor集合不一定是之前响应Prepare请求的Acceptor集合)
Acceptor接受提案
Acceptor可以忽略任何请求(包括Prepare请求和Accept请求)而不用担心破坏算法的安全性 。因此,我们这里要讨论的是什么时候Acceptor可以响应一个请求 。
我们对Acceptor接受提案给出如下约束:
P1a:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案 。
如果Acceptor收到一个编号为N的Prepare请求,在此之前它已经响应过编号大于N的Prepare请求 。根据P1a,该Acceptor不可能接受编号为N的提案 。因此,该Acceptor可以忽略编号为N的Prepare请求 。当然,也可以回复一个error,让Proposer尽早知道自己的提案不会被接受 。
因此,一个Acceptor只需记住:1. 已接受的编号最大的提案 2. 已响应的请求的最大编号 。
Paxos算法原理与推导

文章插图
 
 
Paxos算法描述
经过上面的推导,我们总结下Paxos算法的流程 。
Paxos算法分为两个阶段 。具体如下:
  • 阶段一:
(a) Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求 。
(b) 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案 。
  • 阶段二:
(a) 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor 。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定 。
(b) 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案 。
Paxos算法原理与推导

文章插图
 
 
Learner学习被选定的value
Learner学习(获取)被选定的value有如下三种方案:
Paxos算法原理与推导

文章插图
 
 
如何保证Paxos算法的活性
Paxos算法原理与推导

文章插图
 
 
通过选取主Proposer,就可以保证Paxos算法的活性 。至此,我们得到一个既能保证安全性,又能保证活性的分布式一致性算法——Paxos算法 。




推荐阅读