三个角色:proposers,acceptors,learners
提议有两个阶段,proposer向acceptor发出prepare阶段,proposer向acceptor发出accept阶段。
最后learner根据acceptor的状态学习到一致状态。
提议包括提议编号n,提议内容v
第一阶段a:proposer向所有acceptor广播提议n,
第一阶段b:acceptor承诺proposer不会接收提议编号小于n的提议
第二阶段a:
第二阶段b:acceptor接收提议后,如果提议编号不违反自己的承诺,则接收该提议。
阶段一 提议者Proposer:向接受者Acceptor广播预提案,附带接下来提案Proposal的proposal_id 接受者Acceptor:收到预提案后更新a_proposal_id = max(proposal_id,a_proposal_id)
阶段二 提议者Proposer:向接受者Acceptor广播提案,和之前的预提案共享同一个proposal_id 接受者Acceptor:如果收到的提案的proposal_id>= a.proposal_id,那么接受这个提案,更新a_proposal_id = max(proposal_id,a_proposal_id)
第二遍:
共识算法的三个安全要求:
1.选择的值必须是被提议过的值
2.所有提议的值中,只选择一个
3.除非一个值被选中过,否则线程不会learn到它
三种角色:
proposer,acceptor,learner。每个线程可能扮演多个角色
通讯问题(非拜占庭模型,没有恶意错误):
agents以任意速度通信,有可能因为停止或重启而失败,所以需要每个agents有日志和恢复功能。
消息的传输可能花费任意时间,可能被复制,丢失,但不会出现错误数据。
目标问题:对一个值得选择达成共识
1.单点acceptor
2.多个acceptor---》有可能多个proposer在不同acceptor上被接收到的顺序不同,如何达成一致
3.每个acceptor只能接收一个提议,那么必然存在一个多数派接受了同一个提议值,即达成共识
4.在没有失败和消息丢失的情况下,即使只有一个proposer提议了一个值,也要选出一个共识,引入了P1需求:
P1:一个acceptor必须接收它的第一个提议值。
引入了一个问题,多个acceptor同时接收了多个proposer提议的多个值,没有一个值被多数派接收
所以每个acceptor必须被允许接收多个提议。同时为了跟踪一个acceptor可能接受的多个提议,每个提议加上一个序列号,不同提议的序列号不同。如果一个提议被多数acceptor接收,那么这个提议被选中。可以允许多个提议同时被选中,但这些提议的内容必须相同。
P2:如果提议内容v被选中,那么被选中的具有更高序列号的提议,内容必须都是v。
因为想被选中,必须至少被一个acceptor接收,所以P2需求可以转化为P2a需求
P2a:如果提议内容v被选中,那么任何acceptor接收的每个更高序列号的提议都有内容v。
但因为P1,可能存在这样的情况,一个没有接收到任何提议的acceptor c,和一个刚刚睡醒的proposer,后者提议了一个更高序列号的不同值,根据P1,c必须接收它。但这与P2a违背,于是引出了P2b
P2b:如果提议内容v被选中,那么任何proposer提议的任何更高序列号,都必须有提议内容v。
因为一个提议要被acceptor接收前,必须由proposer发出。所以P2b证明了P2a。
为了发现如何满足P2b,假设多个提议【m,v】,希望任何序列号n>m的提议都有值v。
想要序列号m的提议被选中,必须有一个acceptor多数派C,接受了序列号m的提议,所以推导出:
C中每个acceptor都接受了一个序列号在m-n-1的提议并且内容为v。
因为任何包含多数派acceptor的集合S,都与C有至少一个公共成员,我们可以推导出,序列号n的提议内容为v通过保证P2c条件:
P2c:对任何的v,n,如果一个[n,v]提议被发出,那么有一个包含acceptor多数派的集合S,或者S中没有任何一个acceptor接受过小于n的提议,或者v是S集合中序列号小于n的最大序列号提议的提议值。
为了满足P2c,提议者像发出系列号n的提议之前,必须学习小于序列号n的最大序列号提议(已经或将要被acceptor多数派接收的)。学习已经被接受的提议很容易,而预测未来很难。所以让acceptor做出承诺,不接收任何序列号小于n的提议。
于是得到以下算法:
1.一个proposer选择提议内容n,发到一个集合中的每个acceptor,要求他回应:
不接收比n序列号更小的提议
如果有的话,返回小于n的最大序列号提议。、
这叫做prepare过程。
2.如果一个提议从多数accetpor中得到请求的响应,那么他就可以发出一个[n,v]的提议,其中,v或者是所有响应中最大序列号的提议内容,或者如果响应中没有任何返回的提议,那么当前proposer选择任意value。
这叫组accept过程。
learning a chosen value
必须找到一个提议,被acceptor多数派接收。
第一种方法,每个acceptor接收提议时,都通知所有learner,很快,但效率低
第二种方法,因为非拜占庭错误,所以可以相信其他acceptor接收到的信息。让每个acceptor对应一个learner,需要多一轮时间,在learners之间学习到被选中的值。
出现的问题:
两个proposer互相覆盖,构成死锁。互相发送更大的序列号到acceptor上,让acceptor承诺不接收更小的序列号,不断重复phase1操作,无法尽到phase2