paxos:是一种一致性算法,主要用于数据一致性中,是一种基于消息传递且具有高度容错性的一致性算分。
解决的问题:如何在分布式环境中,快速准确地在集群内部对某个数据的值达成一致,并且保证不发生机器宕机或网络异常等其他异常,都不会破坏整个系统的一致性。
paxos原理:
相关概念:角色
(1)提议者proposer:进行提议的角色
(2)批准者acceptor:通知提议的角色
(3)学习者learner:感知被选定的提议
具体实现时,一个进程可能同时充当多种角色
提案proposal:最终达成一致的value就在提案中,包含编号n和内容value
法定集合性质:称超过半数的进程组成的集合为法定集合,两个法定集合必然存在非空集合,即至少有一个公共进程。
前提条件:通信是可靠的不会被篡改的,但可以存在丢失延迟问题
paxos协议流程:
(1)预提案阶段
提议者:向接受者广播预提案,附带提案的proposal_id
接受者:收到预提案后更新a_proposal_id=max(proposal_id,a_proposal_id),如果预提案的 proposal_id>a_proposal_id,接受者回复记录的接受过的proposal_id最大的提案
(2)提案阶段
提议者:等待直到收到大多数接受者对预提案的回复,从所有回复的提案组成的法定集合数目 的提案集合k中挑选proposal_id最大的提案,依此值作为本次提案的值,若k是空集, 那么可以给提案任意赋值。再把提案广播给接受者们,提案和预提案共享一个 proposal_id
接受者:若收到的proposal_id>=a.proposal_id,接受这个提案,更新 a_proposal_id=max(proposal_id,a_proposal_id),更新记录的提案
缺点及优化措施:
(1)活锁:当某一propaser提交的proposal被拒绝时,可能因为acceptor承诺返回了更大的编号propasal,因此propose人、提高编号继续提交,如果两个proposer都发现自己的编号过低转而提高更高编号proposal,会导致死循环,即活锁现象
解决方案:二进制指数退避算法
(2)效率低:每一个完整的提议都要经过两大轮请求返回;multi-paxos先提出leader后续每次仅需一轮
(3)实现困难:这是共识算法普遍存在的问题
Paxos算法伪代码描述如下:
(1)获取一个Proposal ID n,为了保证Proposal ID唯一,可采用时间戳+Server ID生成;
(2)Proposer向所有Acceptors广播Prepare(n)请求;
(3)Acceptor比较n和minProposal,如果n>minProposal,minProposal=n,并且将 acceptedProposal 和 acceptedValue 返回;
(4)Proposer接收到过半数回复后,如果发现有acceptedValue返回,将所有回复中 acceptedProposal最大的acceptedValue作为本次提案的value,否则可以任意决定本次提案 的value;
(5)到这里可以进入第二阶段,广播Accept (n,value) 到所有节点;
(6)Acceptor比较n和minProposal,如果n>=minProposal,则 acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;否则, 返回minProposal。
(7)提议者接收到过半数请求后,如果发现有返回值result >n,表示有更新的提议,跳转到1; 否则value达成一致。
Multi-Paxos算法
基于Basic Paxos做了两点改进:
针对每一个要确定的值,运行一次Paxos算法实例,形成决议。每一个Paxos实例使用唯一的Instance ID标识。
在所有Proposers中选举一个Leader,由Leader唯一地提交Proposal给Acceptors进行表决。这样没有Proposer竞争,解决了活锁问题。在系统中仅有一个Leader进行Value提交的情况下,Prepare阶段就可以跳过,从而将两阶段变为一阶段,提高效率。
Multi-Paxos流程:
Multi-Paxos首先需要选举Leader,Leader的确定也是一次决议的形成,所以可执行一次Basic Paxos实例来选举出一个Leader。选出Leader之后只能由Leader提交Proposal,在Leader宕机之后服务临时不可用,需要重新选举Leader继续服务。在系统中仅有一个Leader进行Proposal提交的情况下,Prepare阶段可以跳过。
Multi-Paxos通过改变Prepare阶段的作用范围至后面Leader提交的所有实例,从而使得Leader的连续提交只需要执行一次Prepare阶段,后续只需要执行Accept阶段,将两阶段变为一阶段,提高了效率。为了区分连续提交的多个实例,每个实例使用一个Instance ID标识,Instance ID由Leader本地递增生成即可。
Multi-Paxos允许有多个自认为是Leader的节点并发提交Proposal而不影响其安全性,这样的场景即退化为Basic Paxos。