zoukankan      html  css  js  c++  java
  • 一致性协议之Paxos算法

    一、算法提出背景

      Paxos算法需要解决的问题就是如何在一个可能发生诸如宕机或网络异常情况的分布式气筒中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。

    二、问题描述

      假设有一组可以提出提案的进程集合,那么对于一个一致性算法来说需要保证一下几点:

      (1)在这些被提出的提案中,只有一个会被选定。

      (2)如果没填被踢出,那么久不会有被选定的提案。

      (3)当一个提案被选定后,进程应该可以获取被选定的提案信息。

      对于一致性来说,安全性需求如下:

      (1)只有被提出的提案才能被选定

      (2)只有一个值被选定

      (3)如果某个进程认为某个提案被选定了,那么这个提案必须是真的被选定的那个。

      在对Paxos算法的讲解过程中,我们不去精确地定义其活性需求,从整体上来说,Paxos的目标就是要保证最终由有一个天会被选定,当提案被选定后,进程最终也能获取到被选定的提案。

      在该一致性算法中,有三种参与角色,我们用Proposer、Acceptor和Learner来表示。在具体的实现中,一个进程可能充当不止一种角色,在这里我们并不关心进程如何映射到各种角色。假设不同参与者之间可以通过收发信息来进行通信,那么:

      (1)每个参与者以任意的速度执行,可能会因为出错而停止,也可能会重启。同时,即使一个天被选定后,所有的参与者也都有可能失败或重启,因此除非那些失败或重启的参与者可以记录某些信息,否则将无法确定最终的值。

      (2)消息在传输过程中可能会出现不可预知的延迟,也可能会重复或丢失,但是消息不会被损坏,即消息内容不会被篡改。

     三、算法陈述

      结合Proposer和Acceptor对提案的处理逻辑,就可以得到如下类似于两阶段提交的算法执行过程。

      阶段一

      1.Proposer选择一个提案编号M(n),然后向Acceptor的某个超过半数的子集成员发送编号为M(n)的Prepare请求。

      2.如果一个Acceptor收到一个编号为M(n)的请求的编号,那么他就会将它已经批准过得最大编号的天作为相应反馈给Proposer,同时该Acceptor会承诺不会再批准任何编号小于M(n)的提案。举个例子来说,假定一个Acceptor已经响应过的所有Prepare请求对应的天编号分别为1、2、...5和7,那么该Acceptor在接收到一个编号为8的Prepare请求后,就会将编号为7的提案作为响应反馈给Proposer。

      阶段二

      1.如果Proposer收到来自半数以上的Acceptor对于其发出的编号为M(n)的Prepare请求和响应,那么它就会发送一个针对[M(n),V(n)]提案的Accept请求给Acceptor。注意,V(n)的值就是收到的响应中编号最大的提案的值,如果响应中不包含任何提案,那么他就是任意值。

      2、如果Accept收到这个针对[M(n),V(n)]提案的Accept请求,只要改Acceptor尚未对编号大于M(n)的Prepare做出响应,他就可以通过这个提案。

      当然,在实际运行过程中,每一个Proposer都可能会产生多个提案,但只要每个Proposer都遵循如上所述的算法运行,就一定能够保证算法执行的正确性。值得一提的是,每个Proposer都可以在任意时刻丢弃一个提案,哪怕针对该提案的请求和响应在提案被丢弃后会到达,但根据Paxos算法的一系列规约,依然可以保证骑在提案选定上的正确性。事实上,如果某个Proposer已经在视图生成更大的提案,那么丢弃一些旧的提案未尝不是一个好的选择,因此,如果一个Acceptor因为已经收到过更大编号的Prepare请求而忽略某个编号更小的Prepare或者Accept请求,那么它也应当通知其对应的Proposer,以便该Proposer也能将该提案进行丢弃。

    四、提案的获取

      在上文中,我们已经介绍了如何来选定一个提案,下面我们再来看看如何让Learner获取提案,答题可以有一下几种方案。

      方案一

        Learning获取一个已经被选定的提案的前提是,该提案已经被板书以上的Acceptor批准。因此,最简单的做法就是一旦Acceptor批准可一个天,就将该提案发送给所有的Learner。

        很显然,这种做法虽然可以让Learner尽快地获取被选定的提案,通知的次数至少为二者个数的乘积。

      方案二

        另一种可行的方案是,我们可以让所有的Acceptor将他们所提案的批准情况,统一发送给一个特定的Learner,在不考虑拜占庭将军问题的前提下,我们坚定Learner之间可以通过消息通信来互相感    知提案的选词能够情况。基于这样的前提,当主Learner被通知的一个提案已经被选定时,它会负责通知其他的Learner。

      方案三

        在讲解方案二的时候,我们提到,方案二最大的问题在于主Learner存在单点问题,即主Learner随时可能出现故障。因此,对方案二进行改进,可以将主Learner的范围扩大,即Acceptor可以将批准的的提案发送给一个特定的Learner集合,该集合中每个Learner都可以在一个提案被选定后通知所有其他的Learner。这个Learner集合中的Learner个数越多,可靠性就越好,但同时网络通信的复杂度也就越高。

    五、通过选主Proposer保证算法的活性

      假设存在一个极端的情况,有两个Proposer依次提出了一系列编号递增的议案,但是最终都无法被选定,具体流程如下:

      Proposer P1提出一个编号为M1的提案,并完成了上述阶段一的流程。但是与此同时,另外一个Proposer P2提出一个编号为M2(M2>M1)的提案,同样也完成了阶段一的流程,于是Acceptor已经不再承诺批准编号小于M2的提案了。因此,当P1进入阶段二的时候,其发出的Accept请求将被Accept忽略,于是P1再次进入阶段一并提出了一个编号为M3(M3>M2)的提案,这又导致P2在第二阶段的Accept请求被忽略,以此类推,提案的选定过程将陷入死循环,如上图所示。

      为了保证Paxos算法流程的可持续性,以避免陷入上述提到的死循环,就必须选择一个主Proposer,并规定只有Proposer才能提出议案。这样一来,只要主Proposer和过半的Acceptor能够正常进行网络通信,那么但凡主Proposer提出一个编号更大的提案被提出或正在接受批准,那么他会丢弃当前这个编号较小的天,并最终能够选出一个编号足够大的提案。因此,如果系统中有足够多的组件能够正常工作,那么通过选择一个主Proposer,整套Paxos算法流程就能够保持活性。

  • 相关阅读:
    poj 2886 Who Gets the Most Candies?(线段树)
    Android开发之SoundPool使用具体解释
    Win8.1应用开发之动态磁贴
    开发人员获取苹果技术支持
    Win32 Windows编程 十二
    华为上机练习题--压缩字符串
    PS 滤镜算法原理 ——马赛克
    JS版汉字与拼音互转终极方案,附简单的JS拼音输入法
    mybatis入门基础----动态SQL
    windows上如何搭建Git Server
  • 原文地址:https://www.cnblogs.com/rainydayfmb/p/7569917.html
Copyright © 2011-2022 走看看