在一个分布式系统中,因为节点故障、网络延迟等各类缘由,根据CAP理论,咱们只能保证一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance) 中的两个。html
对于一致性要求高的系统,好比银行取款机,就会选择牺牲可用性,故障时拒绝服务。MongoDB、Redis、MapReduce使用这种方案。git
对于静态网站、实时性较弱的查询类数据库,会牺牲一致性,容许一段时间内不一致。简单分布式协议Gossip,数据库CouchDB、Cassandra使用这种方案。web
图1算法
如图1所示,一致性问题,能够根据是否存在恶意节点分类两类。无恶意节点,是指节点会丢失、重发、不响应消息,但不会篡改消息。而恶意节点可能会篡改消息。有恶意节点的问题称为拜占庭将军问题,不在今天的讨论范围。Paxos很好地解决了无恶意节点的分布式一致性问题。数据库
1990年,Leslie Lamport在论文《The Part-Time Parliament》中提出Paxos算法。因为论文使用故事的方式,没有使用数学证实,起初并无获得重视。直到1998年该论文才被正式接受。后来2001年Lamport又从新组织了论文,发表了《Paxos Made Simple》。做为分布式系统领域的早期贡献者,Lamport得到了2013年图灵奖。网络
Paxos算法普遍应用在分布式系统中,Google Chubby的做者Mike Burrows说:“这个世界上只有一种一致性算法,那就是 Paxos(There is only one consensus protocol, and that's Paxos)”。分布式
后来的Raft算法、是对Paxos的简化和改进,变得更加容易理解和实现。ide
Paxos原本是虚构故事中的一个小岛,议会经过表决来达成共识。可是议员可能离开,信使可能走丢,或者重复传递消息。对应到分布式系统的节点故障和网络故障。性能
图2优化
如图2所示,假设议员要提议中午吃什么。若是有一个或者多我的同时提议,但一次只能经过一个提议,这就是Basic Paxos,是Paxos中最基础的协议。
显然Basic Paxos是不够高效的,若是将Basic Paxos并行起来,同时提出多个提议,好比中午吃什么、吃完去哪里嗨皮、谁请客等提议,议员也能够同时经过多个提议。这就是Multi-Paxos协议。
Paxos算法存在3种角色:Proposer、Acceptor、Learner,在实现中一个节点能够担任多个角色。
图3
Learner不参与投票过程,为了简化描述,咱们直接忽略掉这个角色。
运行过程分为两个阶段,Prepare阶段和Accept阶段。
Proposer须要发出两次请求,Prepare请求和Accept请求。Acceptor根据其收集的信息,接受或者拒绝提案。
Prepare阶段
Accept阶段
完整算法如图4所示:
图4
Acceptor须要持久化存储minProposal、acceptedProposal、acceptedValue这3个值。
Basic Paxos共识过程一共有三种可能的状况。下面分别进行介绍。
如图5所示。X、Y表明客户端,S1到S5是服务端,既表明Proposer又表明Acceptor。为了防止重复,Proposer提出的编号由两部分组成:
序列号.Server ID
例如S1提出的提案编号,就是1.一、2.一、3.1……
图5 以上图片来自Paxos lecture (Raft user study)第13页
这个过程表示,S1收到客户端的提案X,因而S1做为Proposer,给S1-S3发送Prepare(3.1)请求,因为Acceptor S1-S3没有接受过任何提案,因此接受该提案。而后Proposer S1-S3发送Accept(3.1, X)请求,提案X成功被接受。
在提案X被接受后,S5收到客户端的提案Y,S5给S3-S5发送Prepare(4.5)请求。对S3来讲,4.5比3.1大,且已经接受了X,它会回复这个提案 (3.1, X)。S5收到S3-S5的回复后,使用X替换本身的Y,因而发送Accept(4.5, X)请求。S3-S5接受提案。最终全部Acceptor达成一致,都拥有相同的值X。
这种状况的结果是:新Proposer会使用已接受的提案
图6 以上图片来自Paxos lecture (Raft user study)第14页
如图6所示,S3接受了提案(3.1, X),但S1-S2尚未收到请求。此时S3-S5收到Prepare(4.5),S3会回复已经接受的提案(3.1, X),S5将提案值Y替换成X,发送Accept(4.5, X)给S3-S5,对S3来讲,编号4.5大于3.1,因此会接受这个提案。
而后S1-S2接受Accept(3.1, X),最终全部Acceptor达成一致。
这种状况的结果是:新Proposer会使用已提交的值,两个提案都能成功
图7 以上图片来自Paxos lecture (Raft user study)第15页
如图7所示,S1接受了提案(3.1, X),S3先收到Prepare(4.5),后收到Accept(3.1, X),因为3.1小于4.5,会直接拒绝这个提案。因此提案X没法收到超过半数的回复,这个提案就被阻止了。提案Y能够顺利经过。
这种状况的结果是:新Proposer使用本身的提案,旧提案被阻止
活锁发生的概率很小,可是会严重影响性能。就是两个或者多个Proposer在Prepare阶段发生互相抢占的情形。
图8 以上图片来自Paxos lecture (Raft user study)第16页
解决方案是Proposer失败以后给一个随机的等待时间,这样就减小同时请求的可能。
上一小节提到的活锁,也可使用Multi-Paxos来解决。它会从Proposer中选出一个Leader,只由Leader提交Proposal,还能够省去Prepare阶段,减小了性能损失。固然,直接把Basic Paxos的多个Proposer的机制搬过来也是能够的,只是性能不够高。
将Basic Paxos并行以后,就能够同时处理多个提案了,所以要能存储不一样的提案,也要保证提案的顺序。
Acceptor的结构如图9所示,每一个方块表明一个Entry,用于存储提案值。用递增的Index来区分Entry。
图9
Multi-Paxos须要解决几个问题,咱们逐个来看。
一个最简单的选举方法,就是Server ID最大的当Leader。
每一个Server间隔T时间向其余Server发送心跳包,若是一个Server在2T时间内没有收到来自更高ID的心跳,那么它就成为Leader。
其余Proposer,必须拒绝客户端的请求,或将请求转发给Leader。
固然,还可使用其余更复杂的选举方法,这里再也不详述。
Prepare的做用是阻止旧的提案,以及检查是否有已接受的提案值。
当只有一个Leader发送提案的时候,Prepare是不会产生冲突的,能够省略Prepare阶段,这样就能够减小一半RPC请求。
Prepare请求的逻辑修改成:
当Leader收到超过半数的noMoreAccepted回复,以后就不须要Prepare阶段了,只须要发送Accept请求。直到Accept被拒绝,就从新须要Prepare阶段。
目前为止信息是不完整的。
第1个问题的解决方案很简单,就是Proposer给所有节点发送Accept请求。
第2个问题稍微复杂一些。首先,咱们能够增长一个Success RPC,让Proposer显式地告诉Acceptor,哪一个提案已经被接受了,这个是彻底可行的,只不过还能够优化一下,减小请求次数。
咱们在Accept请求中,增长一个firstUnchosenIndex参数,表示Proposer的第一个未接受的Index,这个参数隐含的意思是,对该Proposer来讲,小于Index的提案都已经被接受了。所以Acceptor能够利用这个信息,把小于Index的提案标记为已接受。另外要注意的是,只能标记该Proposer的提案,由于若是发生Leader切换,不一样的Proposer拥有的信息可能不一样,不区分Proposer直接标记的话可能会不一致。
图10
如图10所示,Proposer正在准备提交Index=2的Accept请求,0和1是已接受的提案,所以firstUnchosenIndex=2。当Acceptor收到请求后,比较Index,就能够将Dumplings提案标记为已接受。
因为以前提到的Leader切换的状况,仍然须要显式请求才能得到完整信息。在Acceptor回复Accept消息时,带上本身的firstUnchosenIndex。若是比Proposer的小,那么就须要发送Success(index, value),Acceptor将收到的index标记为已接受,再回复新的firstUnchosenIndex,如此往复直到二者的index相等。
Paxos是分布式一致性问题中的重要共识算法。这篇文章分别介绍了最基础的Basic Paxos,和可以并行的Multi-Paxos。
在Basic Paxos中,介绍了3种基本角色Proposer、Acceptor、Learner,以及提案时可能发生的3种基本状况。在Multi-Paxos中,介绍了3个须要解决的问题:Leader选举、Prepare省略、完整信息流。
在下一篇文章中,咱们将实现一个简单的demo来验证这个算法,实现过程将会涉及到更多的细节。
Paxos lecture (Raft user study)
YouTube | Paxos lecture (Raft user study)
本做品采用CC BY 4.0许可协议,转载时请注明连接。