美文网首页zookeeper
死磕Zookeeper系列-3-Paxos算法

死磕Zookeeper系列-3-Paxos算法

作者: yulongsun | 来源:发表于2018-01-17 01:22 被阅读92次

    大纲

    https://www.zybuluo.com/yulongsun/note/1012707


    1. Paxos算法是什么?

    Paxos算法是基于消息传递且具有高效容错特性的一致性算法,目前公认的解决分布式一致性问题最有效的算法之一.

    Paxos算法基于2PC,并进行了扩展.

    2. Paxos算法产生背景

    2.1 "拜占庭将军问题"

    拜占庭是古代东罗马帝国的首都,由于地域宽广,守卫边境的多个将军(系统中的多个节点)需要通过信使来传递消息,达成某些一致的决定。但由于将军中可能存在叛徒(系统中节点出错),这些叛徒将努力向不同的将军发送不同的消息,试图会干扰一致性的达成。
    

    2.2 Paxos算法由来

    故事背景是古希腊 Paxos岛上的多个法官在一个大厅内对一个议案进行表决,如何达成统一的结果。他们之间通过服务人员来传递纸条,但法官可能离开或进入大厅,服务人员可能偷懒去睡觉。 
    

    1990 年由 Leslie Lamport 提出的Paxos共识算法,在工程角度实现了一种最大化保障分布式系统一致性(存在极小的概率无法实现一致)的机制。Paxos 被广泛应用在 Chubby、ZooKeeper 这样的系统中,Leslie Lamport 因此获得了 2013 年度图灵奖。

    2.3 产生背景

    在常见的分布式系统中,总会发生节点宕机或网络异常(包括消息的重复、丢失、延迟、乱序、网络分区)等情况。
    Paxos算法主要就是解决如何在一个发生如上故障的分布式系统中,快速正确的在集群内**对某个值达成一致**,并且保证整个系统的一致性。
    
    产生背景产生背景

    3. 算法详解

    3.1 角色&提案

    • [x] 提案(Proposal)
      注意:提案的范围>value.后面会讲到,[提案=编号+Value].也可表示为[M,V].
      以下描述中暂定:提案=P,Value=V.
    • [x] 角色
      1、Proposer :Proposer可以提出提案(Proposal).
      2、Accecptor: Acceptor可以接受提案.一旦接受提案,提案里面的value值就被选定了.
      3、Learner: Acceptor告诉Learner哪个提案被选定了,那么Learner就学习这个被chosen的value.


      概念关系图概念关系图
    • 在具体的实现中,一个进程即可能是Proposer,也可能是Acceptor,也可能是Learner.

    3.2 问题描述

    Paxos算法的核心是一致性。所以将从一致性问题的描述来讲解该算法怎么解决实际问题.
    
    • [x] 对于一个一致性算法的前置条件
      1、在被提出的P中,只有一个V被chosen.
      2、如果没有P被提出,就没有V被chosen.
      3、在P被选定后,进程都可以学习被chose的P.
    • [x] 假设不同角色之间可以通过发送消息来进行通信,那么:
      1、每个角色以任意的速度执行,可能因出错而停止,也可能会重启。一个value被选定后,所有的角色可能失败然后重启,除非那些失败后重启的角色能记录某些信息,否则等他们重启后无法确定被选定的值。(角色有记录信息的功能)。
      2、消息在传递过程中可能出现任意时长的延迟,可能会重复,也可能丢失。但是消息不会被损坏.(即消息内容不会被篡改--拜占庭将军问题)。

    3.3 推导过程--(在于理解过程)

    3.3.1 只有一个Acceptor

    只有一个Acceptor只有一个Acceptor

    一个Acceptor接受一个P,那么只有一个V被选定。
    缺点:如果这个Acceptor宕机,那么整个系统服务不可用。

    3.3.2 多Acceptor

    多Acceptor多Acceptor
    • 问题:如何在多Proposer和多Acceptor情况下,选定一个value?
    • 讲解步骤分两阶段:约定P1和约定P2.

    3.3.2.1 约定P1

    P1:一个Acceptor必须接受一个它收到的第一个P.
    //我的疑问:接受==被选定?

    在此约定在会产生的问题是:如果每个Proposer会产生不同的P,那么多Proposer必定产生多P,发给多个Acceptor。根据约定P1,Acceptor分别接受到P,就会导致不同的V被选定.如下图所示:

    P1会产生的问题P1会产生的问题
    上图,P1会产生的问题:v1、v2、v3都没有被选定,因为他们只有被一个Acceptor接受.
    对于上述问题,我们需要一个额外的约定:

    P1a:一个提案P被选定,需要被半数以上Acceptor接受.

    对于P1a,其实就意味着【一个Acceptor必须接受不止一个提案】.
    显然,这与P1相矛盾,所以需要重新设计提案。原来的设计是:提案P=value,现在重新设计:提案P=提案编号+value,可表示为[M,V].

    新问题:多提案被选定,如何保证被选定的提案P具有相同的value?

    3.3.2.2 约定P2

    P2: 如果提案P[M0,V0]被选定了,那么所有比M0编号更高的,且[被选定]的P,其value值也是V0.

    对于P2中的“被选定”:一个提案要被选定,首先至少要被一个Acceptor批准。因此,可以理解P2为:

    P2a:如果提案P[M0,V0]被选定了,那么所有比M0编号更高的,且[被Acceptor批准]的P,其value值也是V0.

    只要满足P2a,就能满足P2.

    多提案被选择的问题解决了,但是由于网络不稳定或者宕机的原因(不可避免),会产生新问题:

    P2bP2b
    假设有5个Acceptor。Proposer2提出[M1,V1]的提案,Acceptor2~5(半数以上)均接受了该提案,于是对于Acceptor2~5和Proposer2来讲,它们都认为V1被选定。Acceptor1刚刚从宕机状态恢复过来(之前Acceptor1没有收到过任何提案),此时Proposer1向Acceptor1发送了[M2,V2]的提案(V2≠V1且M2>M1),对于Acceptor1来讲,这是它收到的第一个提案。根据P1(一个Acceptor必须接受它收到的第一个提案。),Acceptor1必须接受该提案!同时Acceptor1认为V2被选定。这就出现了两个问题:
        1、Acceptor1认为V2被选定,Acceptor2~5和Proposer2认为V1被选定。出现了不一致。
        2、V1被选定了,但是编号更高的被Acceptor1接受的提案[M2,V2]的value为V2,且V2≠V1。这就跟P2a(如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v)矛盾了。
    

    基于以上问题,所有就有了P2b:

    P2b:如果P[M0,V0]被选定后,任何Proposer产生的P,其值也是V0.

    • 对于P2b中的描述,那么怎样保证:“任何Proposer产生的P,其值也是V0.”呢?
      只要满足P2c即可:

    P2c:对于任意的M、V,如果[M,V]被提出,那么存在一个半数以上的Acceptor组成的结合S,满足以下两个条件中的任何一个:
    ① S中没有一个接受过编号小于M的提案。
    ② S中的Acceptor接受过的最大编号的提案的value为V。

    推导完毕.

    3.4 算法流程

    3.4.1 Propose提出提案

    总体思路如下:

    1、学习阶段:Prepare请求
        Proposer选择一个新的提案P[MN,?]向Acceptor集合S(半数以上)发送请求,要求S中的每一个Acceptor做出如下响应:
        1.1 如果Acceptor没有接受过提案,则向Proposer保证:不再接受编号小于N的提案。
        1.2 如果Acceptor接受过请求,则向Proposer返回【已经接受过的编号小于N的编号最大的提案】。
        
    2、接受阶段:Acceptor请求
        2.1 如果Proposer收到【半数以上】Acceptor响应,则生成编号为N,value为V的提案[MN,V],V为所有响应中编号最大的提案的value.
        2.2 如果Proposer收到的响应中没有提案,那么value由Proposer自己生成,生成后将此提案发给S,并期望Acceptor能接受此提案。
    

    3.4.2 Acceptor接受提案

    Acceptor可以忽略任何请求(包括Prepare请求和Accept请求)而不用担心破坏算法的安全性。因此,我们这里要讨论的是什么时候Acceptor可以响应一个请求。

    我们对Acceptor接受提案给出如下约束:

    P1b:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案。

    如果Acceptor收到一个编号为N的Prepare请求,在此之前它已经响应过编号大于N的Prepare请求。根据P1b,该Acceptor不可能接受编号为N的提案。因此,该Acceptor可以忽略编号为N的Prepare请求。当然,也可以回复一个error,让Proposer尽早知道自己的提案不会被接受。

    因此,一个Acceptor只需记住:1. 已接受的编号最大的提案 2. 已响应的请求的最大编号。


    Acceptor接受提案Acceptor接受提案

    Paxos算法描述

    Paxos算法描述Paxos算法描述

    3.4.3 Learner学习提案

    Learner学习(获取)被选定的value有如下三种方案:


    Learner学习提案Learner学习提案

    4. 如何保证Paxos算法的活性

    如何保证Paxos算法的活性如何保证Paxos算法的活性

    参考:
    1、http://www.cnblogs.com/linbingdong/p/6253479.html
    2、《从Paxos到ZooKeeper》

    相关文章

      网友评论

        本文标题:死磕Zookeeper系列-3-Paxos算法

        本文链接:https://www.haomeiwen.com/subject/wpcyoxtx.html