Paxos - Basic Paxos

Basic Paxos

总的来说,Basic Paxos分成5个角色,俩个阶段,分别是

角色:

1.Client

  Client发送一个请求到分布式系统,比如请求一个文件

1.Proposer

  Proposer接收客户端的请求,并且让Acceptors接受这个请求。当发送冲突时,担任协调者。

2.Acceptors

  一组Acceptors组成法定人数(一群Acceptors),任何发送给Acceptors的消息都必须发送给法定人数,从Acceptors收到的任何消息都应该忽略,

  除非从法定人数内的每个Acceptors都收到一份同样的消息。

3.Learner

  Learner充当协议的复制者,一旦Client的请求被Acceptors通过,Learner就可以执行客户端的请求(执行请求,响应数据给Client),为了保证可用性,Learner可以动态添加。

上面三个角色,任何一个参与者都可以扮演任意角色,但是在一轮共识过程中,只能担任一个角色(在共识形成后Learner才有作用)。

4.Leader

  Paxos需要一个Proposer充当Leader来管理过程。但是可能有多个Proposer相信自己是Leader,协议保证只选择其中的一个,如果有多个Leader,就会出现冲突更新。

Quorums

Quorums表示法定人数,任何俩组法定人数,必须至少有一个Acceptor是重复的,n/2+1。

Phase1

  P1a:Prepare

  prepare过程由Proposer提出一个prepare message,格式是{n},n表示这次议案的编号(n唯一,并且按照时间顺序全局递增)。

      Proposer 把这个议案发给法定人数(一组Acceptors),如果Proposer不能和法定人数通讯,不能开始这个过程。

        注意:prepare message 不能包含提案的值v

     P1b:Promise

  Acceptors一直在等待prepare message,如果Acceptors收到prepare message,必须检查prepare message里面的编号值 n。

  1.如果编号值 n 大于以前收到的任意提案值,Acceptors必须响应promise消息,同样,也必须忽略往后收到编号小于n的消息,

    以前 Accept 过提案,它给Proposer的响应中必须包含先前 Accept 的提案,形式可能是{m,v}(m为提案的编号,v是 Accept 的值)。

      2.编号n小于等于以前收到过的提案编号,Acceptor可以忽略这个提案(假装没有收到),当然,一个更优的做法是响应一个拒绝信息,用于通知Proposer结束这次提案。  

Phase2

  P2a:Accept

  如果Proposer 从法定人数中收到足够多的promise,它需要把值v放进提案。如果有任何一个Acceptors 先前 Accept 过提案,Acceptors 会把 Accept 的提案响应给 Proposer,

      比如是 {m,v}。那么,Proposer必须(must语义)把 v 设置成收到 Promise 内最高提案的值,比如是 z。

      如果所有法定人数 Acceptors 响应说先前没有收到过提案,Proposer 可以设置任意的值 x。

  Proposer发送 Accept 消息给Acceptor,消息的格式为{n,v}(v是 Proposer 选择的值,n是先前 prepare 阶段的提案编号)。

  所以,Acceptors收到的 Accept 消息要么是 { n,z},要么是 { n,x }。

  Accept消息应该理解成 " 请求 "," 请接受这次提案"。

  P2b:Accepted

   法定人数 Acceptors 从Proposer那里收到 { n,v } 的 Accept 消息,当Acceptors 在 P1b 中没有承诺给任何编号大于n的提案时,Acceptors必须接受值 v。

   Acceptors 一旦接受值 v,应该回复一个 Accepted 消息给Proposer 和各个 Learner。

  要不然就是不接受值 v,此时它应该忽略这个请求。

     注意:

    Acceptor可以接受多个提案,在其他Proposer还不知道新决定的值,并且用一个更高的n做编号发起提案就会出现这个情况。在这种情况下,虽然Acceptors在以前已经接受了一个新值,             它仍然可以响应 promise 并且 accept 新值,这些Proposer可能会有不同的值,但是,Paxos协议保证Acceptors都会一致同意一个单一值(新值覆盖旧值)。

缺陷模型

  在多个Proposer发出冲突的Prepare message或者Proposer没有收到法定人数响应(PromiseAccepted),在这些情形下,如果发起新的提案。必须使用一个更高的提案编号

没有任何失败情形下的Basic Paxos流程

  在下图内,1 个Client,1个Proposer,3个Acceptors(法定人数是3),2个Learner,图中表示的是第一轮共识,并且中间没有任何错误发生。

Client   Proposer      Acceptor     Learner
   |         |          |  |  |       |  |
   X-------->|          |  |  |       |  |  Request
   |         X--------->|->|->|       |  |  Prepare(1)
   |         |<---------X--X--X       |  |  Promise(1,{Va,Vb,Vc})
   |         X--------->|->|->|       |  |  Accept!(1,V)
   |         |<---------X--X--X------>|->|  Accepted(1,V)
   |<---------------------------------X--X  Response
   |         |          |  |  |       |  |
在这里,V 是 {Va,Vb,Vc}中的最后一个

Acceptor失败时的Basic Paxos流程

下图表示有一个Acceptors失败了,但是剩余的Acceptors总数仍然占大多数(总共是3个Acceptor,挂了一个,还有俩个Acceptor),所以,Basic Paxos仍然会成功。

Client   Proposer      Acceptor     Learner
   |         |          |  |  |       |  |
   X-------->|          |  |  |       |  |  Request
   |         X--------->|->|->|       |  |  Prepare(1)
   |         |          |  |  !       |  |  !! FAIL !!
   |         |<---------X--X          |  |  Promise(1,{Va, Vb, null})
   |         X--------->|->|          |  |  Accept!(1,V)
   |         |<---------X--X--------->|->|  Accepted(1,V)
   |<---------------------------------X--X  Response
   |         |          |  |          |  |

冗余的Learner失败时的Basic Paxos的流程

下图表示有一个Learner失败,但是Basic Paxos仍然会成功

Client Proposer         Acceptor     Learner
   |         |          |  |  |       |  |
   X-------->|          |  |  |       |  |  Request
   |         X--------->|->|->|       |  |  Prepare(1)
   |         |<---------X--X--X       |  |  Promise(1,{Va,Vb,Vc})
   |         X--------->|->|->|       |  |  Accept!(1,V)
   |         |<---------X--X--X------>|->|  Accepted(1,V)
   |         |          |  |  |       |  !  !! FAIL !!
   |<---------------------------------X     Response
   |         |          |  |  |       |

Proposer 失败时的Basic Paxos流程

在下面这个图中,Proposer在提出一个值的过程中失败了, 在Acceptor的Accepted返回之前,并且Proposer发送了一个Accept给了法定人数中的某一个Acceptor。

同时,出现了一个新的Leader(某个Proposer,图中没有画出来),注意图中画了俩轮共识,从上往下

Client  Proposer        Acceptor     Learner
   |      |             |  |  |       |  |
   X----->|             |  |  |       |  |  Request
   |      X------------>|->|->|       |  |  Prepare(1)
   |      |<------------X--X--X       |  |  Promise(1,{Va, Vb, Vc})
   |      |             |  |  |       |  |
   |      |             |  |  |       |  |  !! Leader fails during broadcast !!
   |      X------------>|  |  |       |  |  Accept!(1,V)
   |      !             |  |  |       |  |
   |         |          |  |  |       |  |  !! NEW LEADER !!
   |         X--------->|->|->|       |  |  Prepare(2)
   |         |<---------X--X--X       |  |  Promise(2,{V, null, null})   -------响应Promise带上先前的Accept的提案,注意后俩个是null。
   |         X--------->|->|->|       |  |  Accept!(2,V)
   |         |<---------X--X--X------>|->|  Accepted(2,V)
   |<---------------------------------X--X  Response
   |         |          |  |  |       |  |

多个Proposers冲突的Basic Paxos流程

多个Proposers都相信自己是leader的时候最复杂,比如,当前的leader挂了,待会又恢复了,但是其他的Proposers已经变成了新的leader。从错误中恢复的leader没有学习到最新情况,

准备开始一轮冲突的操作。如下图所示。有4轮的失败情形,这个情况可能会持续下去(图的最下方)

Client   Leader         Acceptor     Learner
   |      |             |  |  |       |  |
   X----->|             |  |  |       |  |  Request
   |      X------------>|->|->|       |  |  Prepare(1)
   |      |<------------X--X--X       |  |  Promise(1,{null,null,null})
   |      !             |  |  |       |  |  !! LEADER FAILS
   |         |          |  |  |       |  |  !! NEW LEADER (knows last number was 1)
   |         X--------->|->|->|       |  |  Prepare(2)
   |         |<---------X--X--X       |  |  Promise(2,{null,null,null})
   |      |  |          |  |  |       |  |  !! OLD LEADER recovers
   |      |  |          |  |  |       |  |  !! OLD LEADER tries 2, denied
   |      X------------>|->|->|       |  |  Prepare(2)
   |      |<------------X--X--X       |  |  Nack(2)
   |      |  |          |  |  |       |  |  !! OLD LEADER tries 3
   |      X------------>|->|->|       |  |  Prepare(3)
   |      |<------------X--X--X       |  |  Promise(3,{null,null,null})
   |      |  |          |  |  |       |  |  !! NEW LEADER proposes, denied
   |      |  X--------->|->|->|       |  |  Accept!(2,Va)
   |      |  |<---------X--X--X       |  |  Nack(3)
   |      |  |          |  |  |       |  |  !! NEW LEADER tries 4
   |      |  X--------->|->|->|       |  |  Prepare(4)
   |      |  |<---------X--X--X       |  |  Promise(4,{null,null,null})
   |      |  |          |  |  |       |  |  !! OLD LEADER proposes, denied
   |      X------------>|->|->|       |  |  Accept!(3,Vb)
   |      |<------------X--X--X       |  |  Nack(4)
   |      |  |          |  |  |       |  |  ... and so on ...

注意:
  上面图中的描述和 Accepted 处的描述有点不同,在 Accepted 中的描述是,Acceptors可以忽略这个Accept请求,但是,在上图中,Acceptors回复了一个Nack,并且带上了最新的提案编号,
  最坏的情况下,这个冲突会持续冲突下去,谁也不能提交成功

  

上一篇:Linux主机系统加固


下一篇:第4篇:如何发现隐藏的 Webshell 后门(分享一些最近无聊看到的奇怪的知识)