一致性协议之Paxos

纵饮孤独 提交于 2020-02-15 09:06:29
  • 简述:用于解决分布式系统中数据一致性问题
  • 推导过程:在Paxos算法中,有三种角色,分别是Proposer(负责提案),Acceptor(负责决策)和Learner(学习最终提案),Paxos的推导是建立在这两个基础之上的:
    • 消息在传输过程中可能会丢失,但不会被篡改。因为分布式系统一般在内网集群中,不容易被篡改,并且通过校验就可以简单判断是否被篡改
    • 每个参与者可能会发生异常,包括数据丢失,关机等

  在Paxos原始论文(Paxos Made Simple)中,作者是通过不断添加约束条件来推导该算法的 。首先,最简单的方式是选定一个Acceptor,但这种方式容易存在单点故障,因此需要有多个Acceptor,并且规定足够多Acceptor同意的提案才能被选定,后面再讨论足够多是多少。

  首先,即使只有一个提案被提出,也应该有提案被选定,因此有了第一个约束条件:

    P1:Acceptor必须同意它收到的第一个提案

  在P1的基础之上,可能会有这种情况,有n个Proposer,分别向一个Acceptor(总共也n个)提交提案,每个Acceptor都会同意它接受到的第一个提案,此时并不会有一个提案被多数Acceptor批准,如图:

  

  或者是只有两个提案被同时提出,但分别被一般Acceptor批准,最终也无法得到最终提案,如图(红色问号代表不可达):

  因此,P1是不完备的,在P1基础之上 ,需要新增约束:

  P2: 一个提案被选定需要半数以上Acceptor批准

  在P1,p2的基础之上,还有个隐含约束,即一个Acceptor必须能够批准不止一个提案,因为假设每个Acceptor只能批准一个提案的话,又会出现上图中的情况。为了保证最终能够选出一个提案,在Paxos中引入全局编号的概念,提案的形式变为[编号,Value]这样的KV形式,当一个具有某个Value的提案被半数以上Acceptor批准了,该提案就被选定了,注意,此时被选定的提案是表示具有相同Value的一批提案。因此,虽然允许多个提案被选定,但是必须保证这些提案具有相同的Value,这样才能得到最终的提案。因此,可以引出如下约束:

  P3:如果编号为M0,Value为V0的提案被选定了([M0,V0]),那么以后被选定的提案(编号更大的)其值也必须是V0

  因为各个角色之间的通信是异步的,一个提案[M0,V0]可能在某个Acceptor还未收到任何提案的时候就被选定了,如果此时这个Acceptor收到一个编号更大,但值不等于V0的提案,根据P1的约束,Acceptor必须同意该提案,此时又与P3相悖,因此,可将P3改为:

  P3-1:如果一个提案[M0,V0]被选定了,那么之后的Proposer产生的编号更高的提案其值必须为V0

  这个约束是对Proposer进行约束,但是现实情况是Proposer在提案的时候也许并不知道已经有提案被选定以及具体被选定的Value,因此需要找到另外的约束条件来确保P3-1的实现。考虑这样一个约束:

  P3-2:如果提案[Mn,Vn]被提出,那么肯定存在一个由半数以上Acceptor组成的集合S,满足以下条件的一个:

    • S中不存在批准过编号小于Mn提案的Acceptor
    • S中Acceptor批准过的编号小于Mn的提案中,编号最大的提案的Value为Vn

  首先证明由P3-2可以推出P3-1,即满足P3-2的约束即可满足P3-1的约束。采用反证法来证明,假设方案[M0,V0]被选定,这时某个Proposer提出方案[Mn,Vn](Mn=M0+1,Vn不等于V0),则因为[M0,V0]肯定被半数以上Acceptor批准,即条件一不成立,根据条件二肯定存在集合S1(半数以上),其中Acceptor已经接受的所有编号小于Mn的提案中编号最大提案的为Vn,由于S1和批准提案[M0,V0]时的大多数集合之间肯定有交集,因此与条件二矛盾,因此假设不成立,所以由P3-2可以推出P3-1,即P3-2的约束性更强。

  下面来看P3-2是如何保证实施的。用因果关系来分析,其实P3-2是规定了Proposer如何产生提案,如果某个Proposer要产生提案[Mn,Vn],要么没有Value被选定了,要么就是有有Value被选定,但编号小于Mn且被批准的方案中编号最大的方案值为Vn。当每个Proposer按照这种约束条件来生成提案时,即可满足P3-2。通过观察发现,只要Proposer在生成提案之前询问Acceptor,得到他们的最高编号以及是否选择了某个Value,Proposer再根据Acceptor的回答生成具体的提案进行提交即可。其实P3-2的整体实现思路就是:如果某个值V0被选定了,那么以后提案的值就为V0,否则Proposer可以自行决定提案的值,具体做法就是预先咨询,根据反馈决定之后再做提交,这也是一种典型的消息传递模型。

  同时P3-2也解决了P1的不完备问题,因为Proposer提交的Value是受Acceptor限制的,就不会在一次选举中提交两个不同的Value,即使能提交也会因为Proposal编号问题有一个会被拒绝,从而能保证能形成多数派。于是,在P3-2的基础之上,可以得到Paxos算法的工作机制。

  • Paxos算法流程
  1. Prepare阶段:
    • Proposer获取编号Mn,然后向半数以上Acceptor发送prepare请求
    • 若Acceptor收到Proposer编号为Mn的prepare请求,如果Mn大于它相应过的所有prepare请求,它便会将编号最大的方案反馈给Proposer,同时不再批准任何编号小于Mn的提案  
  2. Accept阶段
    • 如果Proposer收到半数以上Acceptor对其编号为Mn的prepare请求的响应,它便会发送提案[Mn,Vn]给这些Acceptor,其中Vn就是prepare请求反馈的值,如果反馈中不包含值,则Proposer可以自行生成Vn
    • 如果Acceptor收到[Mn,Vn]提案的请求,只要该Acceptor尚未对编号大于Mn的prepare请求做出响应,它就可以通过这个提案  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!