区块链快速入门(三) | 您所在的位置:网站首页 › 区块链共识机制有哪些 › 区块链快速入门(三) |
一、CFT简介
CFT(Crash Fault Tolerance),即故障容错,是非拜占庭问题的容错技术。 Paxos 问题是指分布式的系统中存在故障(crash fault),但不存在恶意(corrupt)节点的场景(即可能消息丢失或重复,但无错误消息)下的共识达成问题,是分布式共识领域最为常见的问题。最早由Leslie Lamport用 Paxon 岛的故事模型来进行描述而得以命名。解决Paxos问题的算法主要有Paxos系列算法和Raft算法,Paxos算法和Raft算法都属于强一致性算法。 二、Paxos算法 1、Paxos算法产生背景在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生任何异常,都不会破坏整个系统的一致性。 1990年,Leslie Lamport 在论文《The Part-time Parliament》中提出了Paxos共识算法,在工程角度实现了一种最大化保障分布式系统一致性(存在极小的概率无法实现一致)的机制。Leslie Lamport作为分布式系统领域的早期研究者,因为相关成果获得了2013年度图灵奖。 Leslie Lamport在论文中将Paxos问题表述如下: 希腊岛屿Paxon上的执法者在议会大厅中表决通过法律(一次Paxos过程),并通过服务员(proposer)传递纸条的方式交流信息,每个执法者会将通过的法律记录在自己的账目上。问题在于执法者和服务员都不可靠,他们随时会因为各种事情离开议会大厅(服务器拓机或网络断开),并随时可能有新的执法者进入议会大厅进行法律表决(新加入机器),使用何种方式能够使得表决过程正常进行,且通过的法律不发生矛盾(对一个值达成一致)。 Paxos过程中不存在拜占庭将军问题(消息不会被篡改)和两将军问题(信道可靠)。 Paxos是首个得到证明并被广泛应用的共识算法,其原理类似两阶段提交算法,进行了泛化和扩展,通过消息传递来逐步消除系统中的不确定状态。 作为后续很多共识算法(如 Raft、ZAB等)的基础,Paxos算法基本思想并不复杂,但最初论文中描述比较难懂,甚至连发表也几经波折。2001年,Leslie Lamport专门发表论文《Paxos Made Simple》进行重新解释,其对Paxos算法的描述如下: Phase1 (a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors. (b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered pro-posal (if any) that it has accepted. Phase 2 (a) If the proposer receives a response to its prepare requests (numbered n) from a majority of acceptors, then it sends an accept request to each of those acceptors for a proposal numbered n with a value v , where v is the value of the highest-numbered proposal among the responses, or is any value if the responses reported no proposals. (b) If an acceptor receives an accept request for a proposal numbered n, it accepts the proposal unless it has already responded to a prepare request having a number greater than n. Paxos算法目前在Google的Chubby、MegaStore、Spanner等系统中得到了应用,Hadoop中的ZooKeeper也使用了Paxos算法,但使用的算法是原始Paxos算法的改进算法。通常以Paxos算法为基础,在实现过程中处理实际应用场景中的具体细节,可以得到一个Paxos改进算法。 3、Paxos算法原理Paxos算法的基本思路类似两阶段提交:多个提案者先要争取到提案的权利(得到大多数接受者的支持);成功的提案者发送提案给所有人进行确认,得到大部分人确认的提案成为批准的结案。 Paxos协议有三种角色:Proposer(提议者),Acceptor(决策者),Learner(决策学习者)。 Paxos 是一个两阶段的通信协议,Paxos算法的基本流程如下: 对于提案ID的选择,《Paxos made simple》中提到的是让所有的Proposer都从不相交的数据集合中进行选择。 Google的Chubby论文中给出提案ID的生成算法如下:假设有n个Proposer,每个编号为 ir(0P1的0,因此P1重新计算编号:new P1 = 1*3+1 = 4; 2) P3以编号2提交,发现小于P1的4,因此P3重新编号:new P3 = 1*3+2 = 5。 5、Paxos算法的活锁如果两个提案者恰好依次提出更新的提案,则导致活锁,系统会永远无法达成共识(实际发生概率很小)。活锁没有产生阻塞,但是一直无法达成一致。 活锁有三种解决方案: A、在被打回第一阶段再次发起PrepareRequest请求前加入随机等待时间。 B、设置一个超时时间,到达超时时间后,不再接收PrepareRequest请求。 C、在Proposer中选举出一个leader,通过leader统一发出PrepareRequest和AcceptRequest。 6、Paxos算法异常处理Paxos算法在执行过程中会产生很多的异常情况:Proposer宕机,Acceptor在接收Proposal后宕机,Proposer接收消息后宕机,Acceptor在Accept后宕机,Learner宕机,存储失败等等。 为保证Paxos算法的正确性,Proposer、Aceptor、Learner都需要实现持久存储,以做到Server恢复后仍能正确参与Paxos处理。 Proposer存储已提交的最大proposal编号、决议编号(instance id)。 Acceptor存储已承诺(promise)的最大编号、已接受(Accept)的最大编号和Value、决议编号。 Learner存储已学习过的决议和编号。 7、Paxos算法应用Paxos算法只有两种情况下服务不可用:一是超过半数的Proposer异常,二是出现活锁。前者可以通过增加Proposer的个数来降低由于Proposer异常影响服务的概率,后者本身发生的概率就极低。 Paxos是分布式系统一致性协议的基础,其它的协议(raft、zab等)都是Paxos协议的改进版本。Paxos侧重理论,实现Paxos非常困难。 微信后台生产级Paxos类库PhxPaxos实现:https://github.com/Tencent/paxosstorehttps://github.com/tencent-wechat/phxpaxos 基于Paxos算法的改进算法的资料集合:https://github.com/dgryski/awesome-consensus 三、三军问题 1、三军问题简介三军问题的描述如下: 1) 1支红军在山谷里扎营,在周围的山坡上驻扎着3支蓝军; 2) 红军比任意1支蓝军都要强大;如果1支蓝军单独作战,红军胜;如果2支或以上蓝军同时进攻,蓝军胜; 3) 三支蓝军需要同步他们的进攻时间;但他们惟一的通信媒介是派通信兵步行进入山谷,在那里他们可能被俘虏,从而将信息丢失;或者为了避免被俘虏,可能在山谷停留很长时间; 4) 每支军队有1个参谋负责提议进攻时间;每支军队也有1个将军批准参谋提出的进攻时间;很明显,1个参谋提出的进攻时间需要获得至少2个将军的批准才有意义; 5) 问题:是否存在一个协议,能够使得蓝军同步他们的进攻时间? 三军问题符合Paxos问题场景,参谋和将军需要遵循一些基本的规则: 1) 参谋以两阶段提交(prepare/commit)的方式来发起提议,在Prepare阶段需要给出一个提议编号; 2) 在Prepare阶段产生冲突,将军以提议编号大小来裁决,提议编号大的参谋胜出; 3) 参谋在Prepare阶段如果收到将军返回的已接受进攻时间,在Commit阶段必须使用返回的进攻时间; 2、两参谋先后提议场景
Paxos是对一个值达成一致,Multi-Paxos是连续多个Paxos instance来对多个值达成一致。Multi-Paxos协议中有一个Leader。Leader是系统中唯一的Proposal,在lease租约周期内所有提案都有相同的ProposalId,可以跳过prepare阶段,议案只有accept过程,一个ProposalId可以对应多个Value,所以称为Multi-Paxos。 Multi-Paxos协议是经典的Paxos协议的简化版本,将原来2-Phase过程简化为了1-Phase,从而加快了提交速度。Multi-Paxos要求在各个Proposer中有唯一的Leader,并由Leader唯一地提交value给各Acceptor进行表决,在系统中仅有一个Leader进行value提交的情况下,Prepare的过程就可以被跳过,而Leader的选举则可以由Paxos Lease来完成。 2、PaxosLease在Paxos算法中,如果能够选举出一个leader,那么有助于提高投票的成功率。另外leader在多个决议的选举中有很重要的作用(用于得到决议的连续id)。因此,如何通过某种方法得到一个leader就是PaxosLease所说明的。 Master选举的过程如下:从众多的Node中选择一个作为Master,如果该Master 一直 alive则无需选举,如果master crash,则其他的node进行选举下一个master。选择正确性的保证是:任何时刻最多只能有一个master。 逻辑上Master更像一把无形的锁,任何一个节点拿到这个锁,都可成为master,所以本质上Master选举是个分布式锁的问题,但完全靠锁来解决选举问题也是有风险的:如果一个Node拿到锁,然后crash,会导致锁无法释放,即死锁。一种可行的方案是给锁加个时间(Lease),拿到锁的Master只能在Lease有效期内访问锁定的资源,在Lease timeout后,其他Node可以继续竞争锁,从根本上避免了死锁。 Master在拿到锁后,如果一直alive,可以向其他node”续租“锁,从而避免频繁的选举活动。 五、Raft算法 1、Raft算法简介Paxos 算法的设计并没有考虑到一些优化机制,同时论文中也没有给出太多实现细节,因此后来出现了不少性能更优化的算法和实现,包括Fast Paxos、Multi-Paxos 等。 Raft算法由斯坦福大学的Diego Ongaro和John Ousterhout 2013年在论文《In Search of an Understandable Consensus Algorithm》中提出。Raft算法面向对多个决策达成一致的问题,是对Multi-Paxos的重新简化设计和实现,分解了领导者选举、日志复制和安全方面的考虑,并通过约束减少了不确定性的状态空间。 Raft算法将一致性问题分解为领导选举(leader election)、日志复制(log replication)、安全性(safety)三部分。 2、Raft算法角色Raft算法包括领导者(Leader)、候选者(Candidate)和跟随者(Follower)三种角色,决策前通过选举一个全局的领导者来简化后续的决策过程。领导者决定日志(log)的提交,日志只能由领导者向跟随者单向复制。 Leader:集群中只有一个处于Leader状态的服务器,负责响应所有客户端的请求。 Follower:刚启动时所有节点为Follower状态,响应Leader的日志同步请求,响应Candidate的请求。 Candidate:Follower状态服务器准备发起新的Leader选举前需要转换到的状态,是Follower和Leader的中间状态。 Term(任期):每个Leader都有自己的任期,任期到期就需要开始新一轮选举,在每个任期内,可以没有leader,但是不能出现大于两个的leader。 Raft算法将整个系统执行时间划分为若干个不同时间间隔长度的Term(任期)构成的序列,以递增的数字来作为Term的编号;每个Term由Election开始,在任期内若干处于Candidate状态的服务器竞争产生新的Leader,如果一个候选人赢得了选举,就会在该任期的剩余时间担任领导人;在某些情况下,选票会被瓜分,有可能没有选出领导人,那么将会开始另一个任期,并且立刻开始下一次选举。Raft算法保证在给定的一个任期最多只有一个领导人。 Raft算法典型的过程包括两个主要阶段: (1)Leader选举 当整个系统启动时,所有服务器都处于Follower状态;如果系统中存在Leader,Leader会周期性的发送心跳(AppendEntries RPC)来告诉其它服务器自己是Leader;如果Follower经过一段时间没有收到任何心跳信息,则可以认为Leader不存在,需要进行Leader选举。 在选举前,Follower增加其Term编号并改变状态为Candidate状态,然后向集群内的其它服务器发出RequestVote RPC,Candidate状态持续到发生下面三个中的任意事件: A、赢得选举:Candidate接受了大多数服务器的投票,成为Leader,然后向其它服务器发送心跳(AppendEntries RPC)告诉其它服务器。 B、其它服务器获得选举:Candidate在等待的过程中接收到自称为Leader的服务器发送来的心跳(AppendEntries RPC),如果RPC的Term编号大于等于Candidate自身的Term编号,则Candidate承认Leader,自身状态变成Follower;否则拒绝承认Leader,状态依然为Candidate。 C、一段时间过后,如果没有新的Leader产生,则Term递增,重新发起选举(因为有可能同时有多个Follower转为Candidate状态,导致分流,都没有获得多数票)。 (2)日志复制 Log复制主要作用是用于保证节点的一致性,所做的操作是为了保证一致性与高可用性;当Leader选举出来后便开始负责客户端的请求,所有请求都必须先经过Leader处理。Leader接受到客户端请求后,将其追加到Log的尾部,然后向集群内其它服务器发出AppendEntries RPC,引发其它服务器复制新请求的操作,当大多数服务器复制完后,Leader将请求应用到内部状态机,并将执行结果返回给客户端。 Raft算法已经被多种语言实现,如Go语言、C++、Python等主流开发语言。 Raft算法原理动画演示:http://thesecretlivesofdata.com/raft/ Raft共识算法资源如下:https://raft.github.io/ Raft算法的Go语言实现:https://github.com/goraft/raft |
CopyRight 2018-2019 实验室设备网 版权所有 |