|
女主宣言There is only one consensus protocol, and that's Paxos – all other approaches are just broken versions of Paxos.PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!1简介本文是分布式系统原理和实践的第一篇,笔者在学习的过程参考了原论文以及很多网络文章,感谢那些作者的分享和记录。本文会从Paxos的引入开始,然后对Paxos的流程进行分解和总结,最后对Multi-paxso的特性进行分析。以下所有讨论并不会涉及系统工程实现相关的部分,如果读者对paxos理论这部分已经深入了解,可以自行跳过;在一个系统中,为了避免单节点故障导致数据丢失或服务不可用,通常会把数据复制多份进行保存,并将其存储在不同的数据节点上,以此增加系统的可用性和可靠性,降低数据丢失的可能。但这种方式同时也引入了一个新的问题,就是如何保证处于不同节点上的副本数据是一致完整的,数据副本之间没有任何差异。分布式共识算法就是为解决这个问题而生,而最让人熟知的当属Paxos协议,Google Chubby的作者就曾说,世界上就只有一种一致性协议,那就是Paxos,其他都是Paxos的残缺版本;2Paxos的引入2.1 简介如果要理解Paxos,那必须要知道Paxos解决了什么问题,当然在是解决一致性问题,这里想说的是Paxos如何去解决一致性问题,笔者查阅了论文和网上很多相关的文章,认为最易于记忆的总结是:#确定一个不可变变量的取值Paxos通过确定一个不可变变量的取值来使分布式系统达成一致,对于这个总结可能会存在不少疑惑,变量的意义是什么?为什么不可变?变量确定了有什么作用?系统中的数据都是变化的,随时可能发生增删改;但如果换另一个思路,在一份数据的多个副本中,假设它们的初始状态一致,如果对它们进行系统的操作并且操作的顺序一致,那副本在每个操作结束后的结果也就是一致的,这里我们把各个操作按照顺序记录成[op.1,op.2,...op.i,op.i+1,...],在一个分布式系统中,必然会存在多个进程同时对数据进行操作,那Paxos要做的就是在这些操作中进行选择,并将选择的结果赋值给op.i,这个过程称为确定,即确定op.i的值,一旦op.i确定后就不可再更改。2.2 基本角色Proposer: 提出需要被确定的值;Acceptor: 对提出的值进行确定;Learner: 将确定的值保存和应用;在Paxos中,包括了三类角色,分别是Proposer、Accepter和Learner,一个系统中他们都存在一个或多个。需要被确定的值由Proposer提出,值被提出后发送给接收者Acceptor进行确定,确定成功后由学习者对值进行保存和应用。2.3 确定一个值(单个Accptor)图1如图1,在只有单个Acceptor的系统中,对于多个Propser提出的多个值,Acceptor只要选择第一个到达的就能将值确定下来。相应的问题是单点Acceptor失效的情况下会使得系统不可用,所以需要引入多个Acceptor。2.4 确定一个值(多个Accptor)图2如图2,在具有多个Acceptor的系统中,Proposer可以将提出的值发送给多个Acceptor,只要被大多数(一半以上)Acceptor接受了,那么值就被确定了。为什么是大多数?任何两个由大多数Acceptor组成的集合必然存在交集,即公共的Acceptor,**只要保证Acceptor只能接受(accept)一个值**,那任何两个大多数集合确定的值就是一样的,如果不一样,则集合交集中至少存在一个Acceptor接受了两个值,和条件违背,所以只要**大多数**Acceptor接受了一个值,那值就确定了,并且系统能供容忍少于大多数的Acceptor出现故障。综上,得出的Paxos实现一致性的原始条件是:#Acceptor只能接受一个值图3如图3,如果一个Acceptor能够接受多个值,那如上图所示,提出的两个值都被大多数的Acceptor接受了,那就确定出了两个值而不是一个值,与条件违背;图4如图4,如果一个Acceptor只能接受一个值,那就能保证在一个值被大多数Acceptor接受后就不会出现另一个值再被接受。#P1.Acceptor必须接受收到的第一个值图5如图5,如果一个Acceptor不接受它收到的第一个值,那值的确定就无从谈起。这个条件的引入产生了一个问题,如上图,一个系统中可能会存在多个Properer提出值,Acceptor接受第一个值后无法形成大多数,造成值无法确定,所以Acceptor除了接受第一个值之外,还需要能够接受后续的值,直到值被大多数Acceptor接受后确定下来为止。为了使Acceptor能够对值的多次接受进行标识,从而引入一个编号,编号和值合并称为提议,将编号称为提议号,需要被确定的值称为提议值,至此,提议就包含了提议号和提议值。如果一个提议被确定,那该提议包含的值就被确定了。提议号的生成由系统自行实现,但需要不同的提议具有不同的提议号,并按提出的先后进行递增,即提议号小的提议先被提出,提议号大的后被提出。由于Acceptor能够接受多个提议并且不受数量的限制,一旦一个提议被确定后,为了保证只有一个值被确定,需要对之后的提议进行约束。#P2.如果一个值为v的提议被确定了,那之后确定的提议(提议号更高)的值(提议值)也是v由于提议编号是有序递增的,该条件保证了一旦有提议被确定了,那之后被再确定的提议值是相同的,确保了只有一个值被确定。#P2a.如果一个值为v的提议被确定了,那之后Accpetor接受的提议(提议号更高)的值(提议值)也是v一个提议在被确定之前,需要被Acceptor接受,所以只要满足该条件就能满足P2。#P2b.如果一个值为v的提议被确定了,那之后Proposer提出的提议(提议号更高)的值(提议值)也是v一个提议在被Acceptor之前,需要被Proposer提出,只要满足P2b就能满足P2a。但Proposer如何如何确定提议的提议值v是什么?只要做到有确定的值就用确定值,没有则用自己的值,因此引入P2c。#P2c.如果一个提议号为n,提议值为v的提议被一个Proposer提出,那必然存在一个由大多数Acceptor组成的集合S:(a).集合S中的任何一个Acceptor都没有接受过提议号小于n的提议;(b).v是集合S中的Acceptor接受的最高提议编号m对应的提议值,其中m=highest_promised_number,就接受该提议,并重置accepted_proposal。否则不响应或返回拒绝信息给Proposer;2.6 活锁在上一小节的总结中,可以看到Paxos主要分成两个阶段来完成,Acceptor通过提议编号的大小确定是否接受提议,可能会存在一种场景,如下图7所示:图7Proposer.1收到客户端的请求后发送编号为1的提议,preapare被1,2,3三个Acceptor接收;同时Proposer.3收到客户端的请求后发送编号为2的提议,也被1,2,3三个Acceptor接收;Propser.1收到提议1的大多数prepare请求响应后发出accept请求,因为acceptor已经接收了编号为2的prepare请求,所以会拒绝编号为1的accept请求;由于系统没有确定接受的值,所以Proposer.1会提高自己的提议编号为3,并发送preapre请求,并导致了编号为2的accept请求被拒绝;不断的重复以上的步骤,会导致系统中不能确定被接受的值;上诉的这种现象称为“活锁”;解决的办法可以在Proposer中选出一个leader,由leader进行所有提议的提交,如下图8所示:图83Multi-Paxos通过以上的过程,Paxos可以确定出一个唯一的值,而往往在一个系统中我们需要不断的确定值,最简单的方式可以通过不断的运行Paxos来确定多个值,这个过程中,我们可以称运行一次Paxos为一个实例,一个实例能够确定一个值,如下图9:图9每个实例都需要运行Paxos的两个阶段,如下图10是一个节点允许多个节点同时提交的运行情况:图10n.m : 其中n代表节点,m代表提议号,例如1.1位节点1提出的编号为1的提议;实例1中,节点1提出了编号为1的提议,顺利的被accept实例2中,节点2提出了编号为1的提议,由于节点1已经接收了来自节点2编号为3的提议,所以不会accept编号为1的提议;实例4同理,接收了来自节点3的更高的提议而导致1.2被拒绝;如果只有一个节点提出提议,则流程如下图11:图11由于只有一个节点提出提议,确认的流程就不会被打断,每次提议的编号都一致,只要对一个提议做出承诺后,之后的提议都不需要再承诺,从而省略Paxos的第一阶段,即将对提议编号的承诺扩展到多个实例,如图12:图12由此可以看见,Multi-Paxos是系统的某种特殊场景下表现出来的并加之优化的特性,无需使用leader,在多个节点进行提交的情况下会衰减为朴素的Paxos,为了能够提供更好的性能,可以加强这一特性,可以将请求都通过解决活锁的leader来进行提交。4总结以上,本文从Paxos得基本原理出发,对Paxos中活锁得形成、为何引入leader、以及在特殊场景下表现出来得性质从而简化提议过程进行了简要描述。由于笔者个人水平有限,难免在叙述过程中出现漏洞,望批评指正。参考列表:Paxos算法详解深入理解Paxos算法协议【原创】一步一步理解Paxos算法Paxos、Multi-Paxos详解paxos算法证明过程Paxos理论介绍(1): 朴素Paxos算法理论推导与证明
|
|