参考文档:分布式系列文章——Paxos算法原理与推导 - lzslbd - 博客园
问题产生的背景:
分布式系统出现节点宕机或者网络异常,导致消息延迟、丢失、乱序等情况。该算法就是需要保证,不论啥情况数据都要一致。
相关概念:
三中角色:
Proposer:方案提出者,暂定方案就是某一个类目的值,比如age=11
Acceptor:方案接受者,(假设3个角色都接受)那么暂定认为这个值就是11了
Learners:接受者告诉学习者哪个被接受,learners就认为被接受了
一个进程能充当多个角色。
安全性:
1:只有被提出的value才能被选定
2:有且只有一个value被选定
3:如果某个进程认为value被选定了,那他就必须是真的被选定的那个。
为了保证高可用,acceptor必须有多个
多个proposer只有一个提出者,提出一个方案。一个acceptor只能接收他收到的第一个提案。
这样假设还是有多个方案出现,那就会有下面问题,
所以现在规定超过半数以上的接受才能被选定。这样就必须要让每一个acceptor能接收不同的方案。不然如上图 ,各接收一个,就不满足半数以上的条件,导致没有提案被选中。
所以提案=value是不合理的,现在进行调整
提案都按照提出顺序加上编号,= 编号+value
假设value=11的被选定了,那么每个value对应编号更大的应该也要是11
提案是被acceptor接受的,所以新的约束如下:
假定value=11被选定,比如他对应的编号是10,那么11以后编号的提案被acceptor结受,应该value也必须是1
特殊情况:
1-4 acceptor(超过半数)接受了 2,12,但是acceptor5宕机重启后接收到一个新的方案(1-4当时还没有这个,5宕机也没有接收到前面的),
第一个接收的提案是3,11,按照约P1:acceptor必须接受他收到的第一个提案,并且11的编号3》2,所以5认为该提案被选定,1-4认为2提案被选定。
这样出现不一致,并且编号最高的value也不是11.
所以只要保证:某个提案已经被acceptor选定后,proposer提出的编号更高的方案的value也是和选定的value一致
怎么保证那:
对于任意的n和v被提出,那么存在一个半数以上的acceptor集合满足以下两个条件中的任意一个:
集合中的acceptor都没有接收过编号小于n的提案
集合中的acceptor接收过最大编号的提案的value=v
最终总结:
一:proposer生成提案:
为了满足:某个提案已经被acceptor选定后,proposer提出的编号更高的方案的value也是和选定的value一致,proposer再生成提案前,要先去学习。存在已选定的,就按照已选定的value,不存在才自己来决定。
这样就满足了proposer的一致性。
提案生成算法:
1:(prepare请求)按照顺序选定编号n,给acceptor发送请求,告诉acceptor
a:不再接受任何编号小于n的提案
b:如果已经接受过提案,那么就返回已经接受过的编号小于n的最大编号方案
2:(accept请求)如果proposer接受了半数上的acceptor的响应,那就可以生成提案,n,v(v要么自己决定,要么取已选定的最大编号的v),生成后发送给acceotor集合
二:acceptor接受提案:
一个acceptor只要尚未响应任何编号大于n的Prepare请求,那么他就可以结受编号为n的提案。
所以acceptor要记住两点:1:已接受的最大编号的提案 2:已响应的请求的最大编号
paxos算法描述:
阶段1:
proposer选着一个编号的提案,开始向半数以上的acceptor发送请求
acceptor收到编号为n的请求,如果之前接受的最大编号的value请求小于n,则就把接受过的最大编号响应proposer,让proposer取这个value,同时acceptor不再接受编号小于n的任何提案,否则可以不响应或者响应一个error
阶段2:
如果超过半数的acceptor响应了编号为n的请求,proposer就会发出一个针对n,v提案的accept请求给半数以上的acceptor。v是收到响应中最大编号对应的v,如果没有就按照proposer自定义的。
如果acceptor收到一个编号为n的请求,只要没有对编号大于n的请求做出过响应,就接受这个提案。
Learner学校被选定的value
三种方案:
如何保证Paxos算法的灵活性:



