分布式理论之一:Paxos算法的通俗理解

分布式理论之一:Paxos算法的通俗理解程序员

维基的简介:Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的"La",此人如今在微软研究院)于1990年提出的一种基于消息传递且具备高度容错特性的一致性算法。算法

Paxos算法目前在Google的Chubby、MegaStore、Spanner等系统中获得了应用,Hadoop中的ZooKeeper也使用了Paxos算法,在上面的各个系统中,使用的算法与Lamport提出的原始Paxos并不彻底同样,这个之后再慢慢分析。本博文的目的是,如何让一个小白在半个小时以内理解Paxos算法的思想。小白可能对数学不感兴趣,对分布式的复杂理论不熟悉,只是一个入门级程序员。之因此想写这篇博文,是由于本身看了网上不少介绍Paxos算法的文章,以及博客,包括Lamport的论文,感受仍是难以理解,大多过于复杂,本人一直认为,复杂高深的理论背后必定基于一些通用的规律,而这些通用的规律在生活中其实咱们早就遇到过,甚至用过。因此,咱们先忽略Paxos算法自己,从生活中的小事开始谈起。数据库

假若有一群驴友要决定中秋节去旅游,这群驴友分布在全国各地,假定一共25我的,分别在不一样的省,要决定到底去拉萨、昆明、三亚等等哪一个地点(会合时间中秋节已经定了,此时须要决定旅游地)。最直接的方式固然就是建一个QQ群,你们都在里面投票,按照少数服从多数的原则。这种方式相似于“共享内存”实现的一致性,实现起来简单,但Paxos算法不是这种场景,由于Paxos算法认为这种方式有一个很大的问题,就是QQ服务器挂掉怎么办?Paxos的原则是容错性必定要很强。因此,Paxos的场景相似于这25我的相互之间只能发短信,须要解决的核心问题是,哪怕任意的一部分人(Paxos的目的实际上是少于半数的人)“失联”了,其它人也可以在会合地点上达成一致。好了,怎么设计呢?服务器

这25我的找了另外的5我的(固然这5我的能够从25我的中选,这里为了描述方便,就单拿出另外5我的),好比北京、上海、广州、深圳、成都的5我的,25我的都给他们发短信,告诉本身倾向的旅游地。这5我的相互之间能够并不通讯,只接受25我的发过来的短信。这25我的咱们称为驴友,那5我的称为队长。并发

先来看驴友的逻辑。驴友能够给任意5个队长都发短信,发短信的过程分为两个步骤:分布式

第一步(申请阶段):询问5个队长,试图与队长沟通旅游地。由于每一个队长一直会收到不一样驴友的短信,不能跟多个驴友一块儿沟通,在任什么时候刻只能跟一个驴友沟通,按照什么原则才能作到公平公正公开呢?这些短信都带有发送时间,队长采用的原则是赞成与短信发送时间最新的驴友沟通,若是出现了更新的短信,则与短信更新的驴友沟通。总之,做为一个有话语权的人,只有时刻保持倾听最新的呼声,才能作出最明智的选择。在驴友发出短信后,等着队长回复。某些队长可能会回复说,你这条短信太老了,我不与你沟通;有些队长则可能返回说,你的短信是我收到的最新的,我赞成跟你沟通。对于后面这些队长,还得返回本身决定的旅游地。关于队长是怎么决定旅游地的,后面再说。oop

对于驴友来讲,第一步必须至少有半数以上队长都赞成沟通了,才能进入下一步。不然,你连沟通的资格都没有,一直在那儿狂发吧。你发的短信更新,你得到沟通权的可能性才更大。。。。。。性能

由于至少有半数以上队长(也就是3个队长以上)赞成,你才能与队长们进行实质性的沟通,也就是进入第二步;而队长在任什么时候候只能跟1个驴友沟通,因此,在任什么时候候,不可能出现两个驴友都达到了这个状态。。。固然,你能够经过狂发短信把沟通权抢了。。。。设计

对于得到沟通权的那个驴友(称为A),那些队长会给他发送他们本身决定的旅游地(也可能都尚未决定)。能够看出,各个队长是本身决定旅游地的,队长之间无需沟通。事务

第二步(沟通阶段):这个幸运的驴友收到了队长们给他发的旅游地,可能有几种状况:

第一种状况:跟A沟通的队长们(不必定是所有5个队长,可是半数以上)所有都尚未决定到底去那儿旅游,此时驴友A心花盛开,给这些队长发第二条短信,告诉他们本身但愿的旅游地(好比马尔代夫);

可能会收到两种结果:一是半数以上队长都赞成了,因而代表A建议的马尔代夫被半数以上队长都赞成了,整个决定过程完毕了,其它驴友早晚会知道这个消息的,A先去收拾东西准备去马尔代夫;除此以外,代表失败。可能队长出故障了,好比某个队长在跟女友打电话等等,也可能被其它驴友抢占沟通权了(由于队长喜新厌旧嘛,只有要更新的驴友给本身发短信,本身就与新人沟通,A的建议队长不一样意)等等。无论怎么说,苦逼的A还得从新从第一步开始,从新给队长们发短信申请。

第二种状况:至少有一个队长已经决定旅游地了,A可能会收到来自不一样队长决定的多个旅游地,这些旅游地是不一样队长跟不一样驴友在不一样时间上作出的决定,那么,A会先看一下,是否是有的旅游地已经被半数以上队长赞成了(好比3个队长都赞成去三亚,1个赞成去昆明,另一个没搭理A),若是出现了这种状况,那就别扯了,说明整个决定过程已经达成一致了,收拾收拾准备去三亚吧,结束了;若是都没有达到半数以上(好比1个赞成去昆明,1个赞成去三亚,2个赞成去拉萨,1个没搭理我),A做为一个高素质驴友,也不按照本身的意愿乱来了(Paxos的关键所在,后者认同前者,不然整个决定过程永无止境),虽然本身原来可能想去马尔代夫等等。就给队长们发第二条短信的时候,告诉他们本身但愿的旅游地,就是本身收到的那堆旅游地中最新决定的那个。(好比,去昆明那个是北京那个队长前1分钟决定的,去三亚的决定是上海那个队长1个小时以前作出来的,因而顶昆明)。驴友A的想法是,既然有队长已经作决定了,那我就干脆顶最新那个决定。

从上面的逻辑能够看出,一旦某个时刻有半数以上队长赞成了某个地点好比昆明,紧跟着后面的驴友B继续发短信时,若是得到沟通权,由于半数以上队长都赞成与B沟通了,说明B收到了来自半数以上队长发过来的消息,B必然会收到至少一个队长给他发的昆明这个结果(不然说明半数以上队长都没有赞成昆明这个结果,这显然与前面的假设矛盾),B因而会顶这个最新地点,不会更改,由于后面的驴友都会顶昆明,所以赞成昆明的队长愈来愈多,最终必然达成一致。

看完了驴友的逻辑,那么队长的逻辑是什么呢?

队长的逻辑比较简单。

在申请阶段,队长只会选择与最新发申请短信的驴友沟通,队长知道本身接收到最新短信的时间,对于更老的短信,队长不会搭理;队长赞成沟通了的话,会把本身决定的旅游地(或者还没决定这一信息)发给驴友。

在沟通阶段,驴友C会把本身但愿的旅游地发过来(同时会附加上本身申请短信的时间,好比3分钟前),因此队长要检查一下,若是这个时间(3分钟前)确实是当前本身最新接收到申请短信的时间(说明这段时间没有驴友要跟本身沟通),那么,队长就赞成驴友C的这个旅游地了(好比昆明,哪怕本身1个小时前已经作过去三亚的决定,谁让C更新呢,因而更新为昆明);若是不是最新的,说明这3分钟内又有其它驴友D跟本身申请了,由于本身是个喜新厌旧的家伙,赞成与D沟通了,因此驴友C的决定本身不会赞成,等着D一下子要发过来的决定吧。

Paxos的基本思想大体就是上面的过程。能够看出,其实驴友的策略才是Paxos的关键。让咱们来跟理论对应一下。

Paxos主要用于保证分布式存储中副本(或者状态)的一致性。副本要保持一致,那么,全部副本的更新序列就要保持一致。由于数据的增删改查操做通常都存在多个客户端并发操做,到底哪一个客户端先作,哪一个客户端后作,这就是更新顺序。若是不是分布式,那么能够利用加锁的方法,谁先申请到锁,谁就先操做。可是在分布式条件下,存在多个副本,若是依赖申请锁+副本同步更新完毕再释放锁,那么须要有分配锁的这么一个节点(若是是多个锁分配节点,那么又出现分布式锁管理的需求,把锁给哪个客户端又成为一个难点),这个节点又成为单点,岂不是可靠性不行了,失去了分布式多副本的意义,同时性能也不好,另外,还会出现死锁等状况。

因此,说来讲去,只有解决分布式条件下的一致性问题,彷佛才能解决本质问题。

如上面的例子,Paxos解决这一问题利用的是选举,少数服从多数的思想,只要2N+1个节点中,有N个以上赞成了某个决定,则认为系统达到了一致,而且按照Paxos原则,最终理论上也达到了一致,不会再改变。这样的话,客户端没必要与全部服务器通讯,选择与大部分通讯便可;也无需服务器都所有处于工做状态,有一些服务器挂掉,只有保证半数以上存活着,整个过程也能持续下去,容错性至关好。所以,之前看有的博客说在部署ZooKeeper这种服务的时候,须要奇数台机器,这种说法固然有必定来源背景,好比若是是5台,那么任意客户端与任意其中3台达成一致就至关于投票结束,不过6台有何不可?只是此时须要与4台以上达成一致。

Paxos中的Acceptor就至关于上面的队长,Proposer就至关于上面的驴友,epoch编号就至关于例子中申请短信的发送时间。关于Paxos的正式描述已经不少了,这里就不复述了,关于Paxos正确性的证实,由于比较复杂,之后有时间再分析。另外,Paxos最消耗时间的地方就在于须要半数以上赞成沟通了才能进入第二步,试想一下,一开始,全部驴友就给队长狂发短信,每一个队长收到的最新短信的是不一样驴友,这样,就难以达到半数以上都赞成与某个驴友沟通的状态,为了减少这个时间,Paxos还有Fast Paxos的改进等等,有空再分析。

却是有一些问题能够思考一下:在Paxos以前,或者说除了Chubby,ZooKeeper这些系统,其它分布式系统一样面临这样的一致性问题,好比HDFS、分布式数据库、Amazon的Dynamo等等,解决思路又不一样,有空再进行对比分析。

最后谈谈一致性这个名词。

关于Paxos说的一致性,我的理解是指冗余副本(或状态等,但都是由于存在冗余)的一致性。这与关系型数据库中ACID的一致性说的不是一个东西。在关系数据库里,能够连副本都没有,何谈副本的一致性?按照经典定义,ACID中的C指的是在一个事务中,事务执行的结果必须是使数据库从一个一致性状态变到另外一个一致性状态。那么,什么又是一致性状态呢,这跟业务约束有关系,好比经典的转帐事务,事务处理完毕后,不能出现一个帐户钱被扣了,另外一个帐户的钱没有增长的状况,若是二者加起来的钱仍是等于转帐前的钱,那么就是一致性状态。

从不少博文来看,对这两种一致性每每混淆起来。另外,CAP原则里面所说的一致性,我的认为是指副本一致性,与Paxos里面的一致性接近。都是处理“由于冗余数据的存在而须要保证多个副本保持一致”的问题,NoSQL放弃的强一致性也是指副本一致性,最终一致性也是指副本达到彻底相同存在必定延时。

固然,若是数据库自己是分布式的,且存在冗余副本,则除了解决事务在业务逻辑上的一致性问题外,同时须要解决副本一致性问题,此时能够利用Paxos协议。但解决了副本一致性问题,还不能彻底解决业务逻辑一致性;若是是分布式数据库,但并不存在副本的状况,事务的一致性须要根据业务约束进行设计。

另外,谈到Paxos时,还会涉及到拜占庭将军问题,它指的是在存在消息丢失的不可靠信道上试图经过消息传递的方式达到一致性是不可能的。Paxos自己就是利用消息传递方式解决一致性问题的,因此它的假定是信道必须可靠,这里的可靠,主要指消息不会被篡改。消息丢失是容许的。

关于一致性、事务的ACID,CAP,NoSQL等等问题,之后再详细分析。本文的描述也许可能存在一些举例不太恰当的地方,若是错误,欢迎批评指正。

相关文章
相关标签/搜索