paxos算法学习

paxos算法可以说是大名鼎鼎,一方面是因为它是一个很优秀的分布式一致性算法,另一方面也是由于它的晦涩难懂。今天看到了一个博客(Paxos算法原理与推导)深入浅出的讲了一下这个算法,感觉收获很大,于是借此平台写一下自己对该算法的理解,同时也希望能够通过自己写的过程加深对这个算法的理解。

paxos算法的目标

一个算法自然要有一个确定性的目标。作为分布式一致性算法,paxos的目标是:

  • 能够在集群中对于某个数据的值达成一致
  • 不论发生网络异常还是机器宕机,都不会破坏第一条中的一致性

角色

在paxos算法中,主要有三种角色:proposer、acceptor和learner。同一个进程可以扮演三种角色中的任一/二/三种。
proposer负责生成提案给acceptor,acceptor负责接受提案,learner负责学习接受的提案。在这个定义中,提案被定义为对一个值具体是什么的描述。
当一个提案被半数以上的acceptor接受,我们称为该提案被选定

问题描述

  • 只有被提出的value才能被选定
  • 只有一个value被选定,并且
  • 如果某个进程认为value被选定了,那么这个value必须是真正被选定的哪个

约束

为了能够选出来一个一致的值,我们需要对上面三个角色的行为做一定的约束。
首先,为了能够产生选定的提案,需要下面的约束:

P1: 一个Acceptor必须接受它接收到的第一个提案

但是,这个约束会产生一个问题:假设有三个Proposer,三个Acceptor,每个acceptor接受了其中一个的值,那么没有值可以被选定。所以,我们需要允许Acceptor接受多个提案。为了后面描述,我们规定每个提案必须有个代表顺序的编号N,这样提案可以抽象为<N, V>。

但是,这带来一个问题,由于允许Acceptor接受多个提案,会有多个提案被选定。因此,我们引入以下约束来避免该问题:

P2: 如果某个值为v的提案被选定,那么每个编号更高的被选定提案的值也必须是v

在具体实现的时候,P2可以用一个更强的更具体的约束代替:

P2a: 如果某个值为v的提案被选定,那么每个编号更高的被acceptor接受提案的值也必须是v

但是,考虑以下情况:如果一个值v1被选定了,且acceptor 2,3,4,5都接受了该值。但acceptor 1挂了,后面起来后收到了v2的提案,这时候它不知道v1已经被选定了,因此又会接受v2,违反了P2a。所以P2a是在存在acceptor故障的情况下无法实现的,因此还需要更加强的约束:

P2b:如果某个值为v的提案被选定,那么每个proposer之后编号更高的提案的值也必须是v

那么P2b如何实现呢,可以使用P2c:

P2c:对于任一N和V,如果[N, V]被提出,必须存在一个超过半数的acceptor的集合S,满足下列条件之一:

 1. S中的acceptor没有接受过编号为N以下的提案
 2. S接受过的提案中,编号最大的提案的值为V

可以看出,如果满足P2c,那么如果[N, V]被提出,那么一定不会有超过半数的acceptor集合接受了值不为V的提案,也就是满足了P2b。

但是,其实还有关键的一点:在上面的情况中,如果有超过半数的acceptor集合接受了值不为V的提案,那么proposer的提案就需要跟随已经被接受的提案。那么跟随哪个呢,这个需要proposer对acceptor已经接受提案的值来学习得出。
为了满足P2c,我们提出下面的提案生成算法:

  1. proposer提出一个新的提案编号N,然后向半数以上的acceptor发出请求,内容有两点:1)请acceptor不再接受编号小于N的提案;2)如果acceptor之前接受过提案,那么把其中编号最大的响应给proposer。
  2. 如果proposer收到了半数以上acceptor的响应,那么就生成一个提案[N, V],其中V是响应中带值的提案中编号最大的那个V。如果响应中都不带值,那么V可以自选;生成后将提案发给半数以上的acceptor。如果没有收到,那么获取新的N,回到步骤1.

对于acceptor,根据提案生成算法,需要加强为如下约束:

P1a:一个acceptor只要没有响应过任何编号大于N的请求,那么它就可以接受这个编号为N的提案

这样就不违背proposer提出的要求。
在收到请求的时候,需要进行如下步骤以满足约束:

  1. 如果提案编号N小于当前响应提案的最大编号ResN,不响应或响应错误
  2. 如果不满足1,则返回当前接受过的最大编号的提案(如果有的话),并且承诺不再接受编号小于N的提案。
  3. 如果收到的是提案,只要acceptor没有对编号大于N的请求做过响应,那么就接受该提案

综上,可以得到paxos算法。算法分为两阶段:

  • 阶段1: (a) proposer生成一个编号N的请求,发个半数以上的acceptor。
    (b) acceptor收到一个编号为N的请求后,如果N<ResN,直接拒绝该请求;否则返回目前接受的编号最大的提案(如果有的话),同时承诺不再接受编号小于N的提案。
  • 阶段2
    (a) 如果proposer收到了半数以上acceptor的请求回复,那么按照约束生成提案[N, V]
    (b) 如果acceptor收到了提案[N, V],如果没有响应过编号大于N的请求,那么就接受之。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值