paxos算法

目录

一、问题描述

二、算法推导

三、算法内容

四、leaner获取chosen的值

五、progess


 

 

paxos算法解决集群的一致性问题。

 

一、问题描述

有一个集群,集群就是由多个节点组成的系统,每个节点可以担当以下的一个或几个角色:

a)proposer:提议者,可以提出一个提议(proposal),提议的内容就是设置某个值

b)acceptor:判决者,可以针对一个提议判断是否通过。一个acceptor通过提议不代表集群通过提议,集群通过提议的方法待定。

c)leaner:使用提议的结果

要求集群满足一致性:在任一时刻,集群中的值都是唯一的,即无论从哪个可访问的节点访问一个值,得到的结果都是相同的,是确定且唯一的。

再具体一点,需要满足:a)只有提出的提议可以被通过并设置;b)在一次提议过程中,只有一个提议可以被集群通过;c)没有被集群通过的提议无法被获取到,也就是说被部分节点通过,而没有被集群通过的提议无法被获取到

 

二、算法推导

paxos made simple论文中,推导paxos算法的过程大致是:先提出一个算法,再看存在什么问题,针对存在的问题补充/修改算法,我这里也是参照论文中的过程进行介绍。

 

同论文的表示方法,算法用Px表示,例如P1,P2,P1a。

参考论文,集群通过一个proposal用chosen表示。proposal被chosen的条件:半数以上的acceptor都通过proposal,这样可以保证不会同时存在两个proposal被chosen。

 

P1.acceptor必须通过接收到的proposal

如果再附加条件,每个acceptor只能通过一个proposal,会导致:多个proposal同时提出proposal,部分acceptor通过proposal A,部分通过proposal B,部分通过proposal C,但都没有达到半数以上,这样子的结果就是没有一个proposal能被chosen。

所以修改条件:单个acceptor可以同时通过多个proposal,但这可能造成多个proposal被chosen,不同proposal的值一般不同,这样就导致存在多个值被chosen了,不满足一致性。再进行以下修改。

 

P2.每个proposal有一个number(版本),不同的proposal的版本必须不同。可以存在多个proposal被chosen,但被chosen的proposal中,number大的proposal的值,必须和number小的proposal的值相同,值记为v。

我们暂时先不管P2如何实现,可能是number大的proposal的值在accept时被修改成v,也可能是在proposer提出proposal时就必须是v。

如果P2满足,那么一致性是可以满足的,因为不同proposal的number都不同,只有一个最小的number,v就是这个number对应的proposal的值。

 

再看看P2如何满足:

P2a.当一个版本为m值为v的proposal被chosen之后,在所有acceptor上,如果有版本高于m的proposal被通过,它的值必须是v。

比如:

  • proposal[m,v]被chosen,某个acceptor收到一个proposal[n,v1],且n大于m,这个proposal是不能通过的
  • 某个acceptor中已经有一个通过的proposal[n,v1],且n大于m,然后proposal[m,v]被chosen,这种情况也是不允许的

 

要实现P2a,有两个问题:

a)对新接收的proposal,一个acceptor如何知道v。因为部分acceptor可能是没有收到版本为m值为v的这个proposal的,就不能直接拿到v。

b)在版本为m的proposal被chosen之前,如何保证accetpor不通过版本高于m且值不为v的proposal。

 

修改P2a为P2b:

P2b.当一个版本为m值为v的proposal被chosen之后,proposer提出版本比m高的proposal时,值必须是v。

P2b其实是P2a的充分非必要条件,使用P2b的话,实现时就是proposer去查询被chosen的proposal的值v,解决上面的问题a。

要解决问题b,还要求一个隐含条件:proposer提出提议[n,v]有一个前置条件,版本小于n且值不为v的proposal不可能被chosen。

 

再看看如何实现P2b,先分析一下目前的状况:

  • 如果一个proposal[m,v]被chosen,那么一定存在一个集群的acceptor子集C通过了这个proposal,C中的acceptor个数过半。
  • 假设要进行一个proposal[n,?],那么可能存在版本为m~n-1的proposal,这些版本的proposal的值都是v。这里我们是先假设P2b已经满足了,然后对一个新的proposal[n,?]分析一下如何能获取到v。
  • 我们取集群的任意一个acceptor自己S,S的acceptor个数过半,那么自己S和自己C必然存在交集。

根据以上的几个分析,提出P2c来满足P2b:

P2c.对于一个proposal[n,v],要提议这个proposal,必须满足:

存在一个acceptor子集S,S的acceptor个数过半,且满足两个条件之一:1)S中的所有acceptor都满足:没有通过任何版本小于n的proposal;2)v是S中所有acceptor已经通过的proposal中,版本最大的proposal中的值。

 

P2c只保证了proposal[n,v]被chosen之后的场景,不能保证被chosen之前,proposer不提出版本小于n,且值不为v的proposal。也就是之前的问题b,再看看这个问题如何解决。

proposer的算法步骤:

1.proposer选择一个版本n,并发送请求到所有或部分acceptor,要求这些acceptor:

a)保证不通过版本小于n的proposal

b)返回该acceptor已通过的proposal中,版本小于n的proposal中,版本最大的proposal,包括proposal的版本和值

这一步称作prepare

2.如果一个proposer接收到半数以上的acceptor的回复,那么proposer就可以进行proposal的提议,proposal的版本是n,值是v。v有两种情况,一种是prepare过程中没有一个acceptor返回已通过的proposal,那么proposer自己提议一个v,另一种就是有拿到proposal,那么就使用版本最大的proposal的值。

proposer发送prorosal[n,v]到acceptor,acceptor判断是否通过这个请求,这一步叫做accept。

 

然后是acceptor的算法步骤:

1.acceptor可以回复任何prepare请求,并记下prepare过的最大版本号m。但为了节约,acceptor可以只在每次收到超过已记录的最大版本的prepare请求时才回复。

2.acceptor需要忽略版本号小于m的所有accept请求

 

为了满足以上要求,P1需要修改成P1a:

P1a.acceptor回复过的prepare请求的最大版本号为m,那么acceptor只能通过版本号大于等于m的proposal

 

三、算法内容

phase1. prepare

(a)proposer选取一个版本n,发送number为n的prepare请求到半数以上的acceptor

(b)acceptor接收到版本n的prepare请求,而当前回复过的prepare请求的最大版本为m,那么当n>m时,acceptor记录版本n并回复请求;当n<m时,acceptor忽略prepare请求。不同proposal版本号必须不同,不会出现m=n的情况。

补充说明:b中acceptor回复的内容包含已经accept过的版本号最大的proposal[n,v],但如果没有accept过的proposal,那就不用返回值

 

phase2. accept

(a)proposer接收到半数以上的acceptor对版本n的prepare请求的回复之后,可以发送accept请求给这些acceptor,内容是proposal[n,v],v有两种情况,一种是进行prepare时没有收到返回的proposal,那么proposer自己设置值v;另一种是有收到prepare返回的proposal,那就选择一个版本最大的proposal的值设置为v。

(b)acceptor接收到accept请求,内容是proposal[n,v],而当前进行过prepare请求回复的最大版本为m,如果n>=m,那么就accept这个proposal,否则就忽略accept请求。因为经过了prepare请求,正常不会出现n>m的情况。

 

为了优化性能,可以做一些修改,例如:

acceptor要忽略prepare或者accept请求时,告知proposer,有更高版本的prorosal正在进行中,不用再发消息给其他acceptor了。

 

四、leaner获取chosen的值

方法1:每个acceptor回复accept请求后,同时通知给所有leaner。leaner判断proposal被chosen后,就进行learn。安全性高,资源消耗较大。

方法2:每个acceptor回复accept请求后,都只通知某个特定的leaner,leaner判断proposal被chosen后,仅进行learn,并通知其他leaner。存在可用性问题,资源较节省。

折中方法是选择部分leaner进行通知。

 

五、progess

算法存在一个问题:如果有两个proposer,proposer1成功进行phase1后,proposer2使用更高版本进行phase1,那么proposer1进行phase2时就达不到大多数而失败,然后再用更高的版本重新进行phase1,导致proposer2的phase2失败。。。如此循环,就没有proposal可以被chosen了。

可以指定只有一个特定的proposer能发起proposal,需要一个选举特定proposer的算法,multi-paxos解决了该问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值