Paxos学习笔记及图解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/alinyua/article/details/86153013

本文记录了自己对 Paxos 算法的学习和理解,并对多种分区情况进行了讨论,整理了 Paxos 的执行思路并根据本人实践对其中遇到的问题进行了讲解。但还是可能存在理解不到位或者有纰漏的地方,还希望多多指教。

一 从CAP定理到Paxos算法

1 CAP定理

CAP定理是相对于一个分布式计算系统而言的,首先需要了解C、A、P的定义:

  • C:Consistency
    一致性:所有节点持有相同最新数据副本(对外一致)
  • A:Availability
    可用性:所有节点都能提供数据副本,但不一定最新(对外可用,但不一定好用)
  • P:Partition tolerance
    分区容错性:分区即指系统在一定的通信时限内不能达到数据一致性,即区间通信可能失败。分区容错性即允许出现分区

CAP定理指 在一个分布式系统中,无法同时满足 CAP 3个特性。

例子:分布式系统中出现了两个分区 X 和 Y,X和Y分区内部是一致的 ,X 和 Y 无法沟通。则此时:

  1. 如果允许 X 和 Y 中的节点更新状态,则会导致 X 和 Y 的数据不一致,此时丧失了一致性,为 AP
  2. 如果只保留一个分区,将其他分区的节点设置为不可用(通常是保留节点数过半的分区,舍弃其他的分区),则导致可用节点数下降,此时丧失可用性,为 CP
  3. 如果要求 X和Y状态相同且全部可用,则需要 X 和 Y 在同一分区,即该分布式系统不存在分区,即否认了 该分布式系统的 分区容错性,为 AC

2 分析

分区是分布式系统必然面对的问题,如果不允许出现分区的话,有一台主机由于网络问题脱离集群,就会导致系统运行失败,那这个分布式系统是毫无稳定性可言的。

故分区容错性是必须满足的,即可视为 CAP 中的 P 总是成立的。所以 CAP 定理可以进一步理解成:

在满足分区容错性(P)的前提下,一个分布式系统只能满足 一致性(C)或者 可用性(A)。

可选的组合只有 CP 和 AP,这两者各有优缺点,需根据应用场景进行选择。

在实际应用中,一般没有绝对的CP或者AP,一般都是在符合P的情况下,在A和C之间寻求平衡,我们说的CP或者AP通常指的是一种思想的实现或者说选择的倾向。

如在各个注册中心中,Netflix的Eureka是AP的,而Zookeeper和Consul都是CP的。一般认为服务中心对可用性要求比较高,提供过时的服务总比不提供好。而配置中心则对一致性要求比较高。当然这种说法也不绝对。

3 从 CAP 看 Paxos 算法

Paxos 算法的目的是要 在消息可能会延迟、丢失、重复的基于消息传递通信模型的分布式系统中就某个值最终达成一致

这里的“消息可能会延迟、丢失、重复”可理解为 分区容错性 P,“就某个值达成一致”可理解为 一致性 C,在 Paxos 选举期间服务不可用,则是牺牲了 A。

这么说不准确,但可理解为 Paxos 从设计上就是为了在 P 的前提下实现 C。

二 Paxos 算法

Paxos相关概念

Paxos 中有三类角色 ProposerAcceptorLearner,主要交互过程在 ProposerAcceptor 之间。

  • Proposer
    提案者/提议者:提议一个值,用于被投票决议
  • Acceptor
    附议者/接受者:对每个提议进行投票(只接受其中一个提案)
  • Learner
    学习者/被告知者:被告知投票决议的结果,对其学习,不参与投票过程

注意:一个节点可同时担任多个角色。

Paxos算法流程

Paxos分准备阶段和批准阶段两个阶段完成,每个阶段后还需要判断该阶段的结果是否有效是否需要重来,另外需要注意提案编号全局递增且唯一。

  1. 第一阶段:prepare准备阶段(只需携带提案号):
    1. request
      proposer选择一个提案编号n并将prepare请求发送给所在分区中的所有acceptor;
    2. response
      1. 情况1:提案编号n < acceptor的最大提案编号 MaxN
        不回应或回应错误提醒
      2. 情况2:acceptor从未承诺(promise)过提案
        acceptor记录最大提案编号MaxN为n,回应 ok
      3. 情况3:提案编号n > acceptor的最大提案编号 MaxN
        acceptor记录最大提案编号MaxN为n,回应 ok,如果已经接受过提案,则将接受过的提案编号和值(AcceptN和AcceptV)一并回复
  2. 判断:如果propose收到超过半数的ok,则进入批准阶段,否则重新回到准备阶段
  3. 第二阶段:批准阶段(携带提案号和值):
    1. request
      proposer向所有回复ok的acceptor发送accept请求,包括编号n和 上一阶段拿到的最大的AcceptN 所对应的 AcceptV(如果没有已经接受的value,那么它可以自由决定value)。
    2. response
      1. 情况1:提案编号n < acceptor的最大提案编号 MaxN
        不回应或回应错误提醒
      2. 情况2:提案编号n >= acceptor的最大提案编号 MaxN
        批准请求,回应 ok,记录AcceptN=n,AcceptV=value(如果之前已经有AcceptN和AcceptV,这个时候也会覆盖!)
  4. 判断:如果Proposer收到超过半数的ok,则选举结束,将结果通知给 Learner,否则重新回到准备阶段

Paxos 算法流程理解

如果分区节点数没有过半,则对外表现为不可用(内部持续选举,即使已经有统一值)

如果分区节点数过半,则对外表现为可用(内部选举结束,有统一值),这个时候称之为主分区。

其他分区只要在后面连接到主分区的任意一个节点,就会被这个节点的状态同化,实现这个分区与主分区状态一致,重复这个过程,最终实现分布式系统的一致性。

Paxos 要点及解惑

  1. 最终要保证有唯一的状态,所以要求要有过半的节点状态统一才能确定选举结束。(过半指全局过半而非分区内过半),所以每个阶段后面都要校验收到ok回应的节点数,未过半则该阶段操作无需,从准备阶段重新开始
  2. Accepter确定AcceptV的过程就是投票的过程,表决有效则 AcceptV 不可修改,未表决成功的 AcceptV 则可以修改。Acceptor本身不知道表决是否有效,这是依靠规则自动维护的,而非人为设置的。
    达到的效果即是:选举结束之后主分区的节点状态不能被修改,只有主分区同化其他分区而不会有其他分区同化主分区。这一点后面会再作证明。
  3. AcceptV 需要修改说明 该AcceptV 的支持数未过半(表决失败)且有另一未过半的AcceptV对应的AcceptN比它大。
  4. 提案编号越大代表越晚提出,这个时候有更大可能性有Acceptor已经投票了。Proposer会将提案的值修改为有最多Acceptor支持的值。
    这里为 最大的AcceptN 所对应的AcceptV,也就是说最大的AcceptN 所对应的AcceptV更有可能是最多人支持的value

选举结束的分区情况讨论

  1. 情况1(单分区投票)
    如果有一个分区X在审批阶段结束后节点仍过半,其内部形成一致意见 [Nx,Vx],则选举结束,不再讨论。

  2. 情况2(双分区投票)
    如果有另一节点过半的分区Y接触且仅接触到分区X的任意节点,则会在准备阶段收到 [Nx,Vx] 的回应。
    如果批准阶段节点数仍过半,则顺利以 [Ny,Vx] 结束,不再讨论。
    如果批准阶段节点回应数不足,则会增加 [Ny,Vx] 的节点,可视为对下一轮选举无影响。

  3. 情况3(多分区投票)
    如果存在于分区X情况类似的分区Z [Nz,Vz],且 Nz>Nx,此时有节点过半的分区Y接触到分区X的节点和分区Y的节点。
    如果批准阶段节点数仍过半,则顺利以 [Ny,Vz] 结束,不再讨论。
    如果批准阶段节点回应数不足,则会增加 [Ny,Vz] 的节点,可视为对下一轮选举无影响。

如何证明参与选举成功的节点的投票不可被修改?

投票不可被修改即 投票通过的 AcceptV 不可被覆盖。

所以命题为:有一个投票通过的值 [N1,V1] 被投票通过,则该分布式系统中不存在已被某节点接受的[N2,V2]符合条件 ----- N2>N1 && V1<> V2 。

反证法:
假设 有一个投票通过的值 [N1,V1] 被投票通过,且该分布式系统中存在已被某节点接受的[N2,V2]符合条件 ----- N2>N1 && V1<> V2 。

  1. N2已经被某节点接受 -----> [N2,V2] 通过了准备阶段
  2. 由 承诺原则,知 N1 投票通过必然发生在 N2 准备阶段结束 之前(否则有过半节点 应允N2不再接受N1)
  3. 由 过半原则,知 N1 投票通过 和 N2 的准备阶段结束 必然存在交集,故 N2 必然接收到 [N1,V1]
  4. 接收到V1却采用了与V1不同的V2,说明N2的准备阶段存在已经被某节点接受的 [N3,V2],且 N3>N1 && V2 <> V1。
  5. 递归回题目,得出有无穷个 [Nn,Vn] ,假设显然不成立,故原命题正确。

所以投票结束后,再加入的 Proposer 的提议 [N2,V2] 必然符合 N2>N1 && V2==V1。
循环这个过程,最终实现状态一致。

三 Paxos算法流程图

Paxos流程图

四 Paxos 图例

  1. 有两个Proposer,两个都提出 prepare request。来自 Proposer A的 request 先于Proposer B 的 request 到达 Acceptor X和 Acceptor Y,但来自 Proposer B的 request 首先到达 Proposer Z.
    图1
  2. 如果接收(accept)prepare request 的 Acceptor 之前没有看到其他的提议,则 Acceptor 以 prepare response 作出响应,该 prepare response 承诺永远不接受具有较低提议编号的另一提议。
    图2
  3. 后面, Acceptor Z收到了 Proposer A 的 request ,Acceptor X和 Acceptor Y收到了 Proposer B的 request 。
    如果 Proposer 之前已经看到具有更高提议号的 request ,则忽略晚到的 request,如Acceptor Z将忽略 Proposer A的 request(因为2<4)。
    如果 Proposer 之前没有看到更高编号的 request ,它再次承诺忽略具有较低提议编号的任何请求,并发回其已接受的编号最高的提议以及该提议的值。如 Acceptor X和Y 对Proposer B的 request 的做法。
    图3
  4. 一旦 Proposer 收到大多数 Acceptor 的准备响应,它就可以发出接受请求。
    1. 对于Proposer A:由于 Proposer A仅收到表明没有先前提案的答复,因此它向每个具有与其初始提案相同的提议编号和值的 Acceptor 发送 accept request(n = 2,v = 8)。然而,这些 request 都将被忽略,因为目标 Acceptor 都承诺不接受的提议编号低于4 的 request(这是对 Proposer B 的承诺)。

    2. 对于Proposer B:Proposer B 向每个 Acceptor 发送 accept request ,该 request 包含先前使用的提议号(n = 4)以及与其接收的准备响应消息中的最高提议号相关联的值(v = 8)。请注意,这不是 Proposer B 最初提出的值,而是它看到的 prepare response 消息中的最高值。
      图4

  5. 如果 Acceptor accept 的 accept request 的 编号 比其已经看到的更高或相等,则它会 accept 并向每个 Learner 节点发送通知。当 Learner 发现大多数 Acceptor 已接受某个值时,Paxos算法会选择该值
    图5
  6. 一旦Paxos选择了一个值,与其他 Proposer 的进一步沟通就无法改变这个值。
    如果另一个 Proposer(如 Proposer C)发送的 request 的 提案号比之前看到的提案号更高,并且具有不同的值(例如,n = 6,v = 7),则每个接受者都会使用之前的最高提案进行响应(n = 4,v = 8)。这要求提议者C发送包含[n = 6,v = 8] 的接受请求,该请求仅确认已经选择的值。此外,如果一些少数接受者还没有选择一个价值,这个过程可以确保他们最终就同一价值达成共识。(批注,这个过程总是成立的,具体论证过程见上)

参考资料

Paxos 算法 维基百科:https://zh.wikipedia.org/zh-cn/Paxos算法
图解分布式一致性协议Paxos:http://codemacro.com/2014/10/15/explain-poxos/
Paxos By Example(本文图解来自这里):https://angus.nyc/2012/paxos-by-example/

猜你喜欢

转载自blog.csdn.net/alinyua/article/details/86153013
今日推荐