paxos算法之粗浅理解

paxos出身算法

 

paxos出身名门,它爹是没多久前得到图灵奖的在分布式领域大名鼎鼎的Leslie Lamport网络

 

paxos为什么而生并发

 

那么Lamport他老人家为何要搞这个东东呢,不是吃饱了撑的,而是为了解决分布式系统的大难题。分布式系统一分布式

般要求具备高可用性,高可用性通常又是经过冗余也就是多副原本解决,多副本接着又带来了一致性问题,因此分布.net

式系统要解决的问题可简单归结为多副本的一致性问题。怎么解决一致性问题呢?抢答:用事务。何为事务?抢答:视频

多个操做序列的原子性。何为原子性?抢答:还须要您本身去多看书吧。实现事务的方案有两阶段提交协议,和在这blog

个基础上进行了加强的三阶段提交协议。 这两个方案都涉及到两个角色,即协调者(coordinator)和参与者(cohort),协事务

调者要保证操做序列的原子性来实现事务,但它们都存在一些 问题,所以一些著名的系统如Google的Chubby和Yahooip

的Apache ZooKeeper都使用了paxos算法。get

 

两阶段提交协议的消息流程:

 

Coordinator                                         Cohort
                              QUERY TO COMMIT
                -------------------------------->
                              VOTE YES/NO           prepare*/abort*
                <-------------------------------
commit*/abort*                COMMIT/ROLLBACK
                -------------------------------->
                              ACKNOWLEDGMENT        commit*/abort*
                <--------------------------------  
end

两阶段提交协议包含投票(Vote)和提交(Commit)两个阶段,它是一个阻塞的协议,若是参与者给协调者发送YES消息后协调者

永久性地挂了,那么参与者将陷入无限等待中,而且会带来数据不一致的问题。

 

三阶段提交协议的消息流程:

 

 

 

三阶段提交协议在二阶段提交协议的基础上增长了准备提交(Prepared to commit)阶段,解决了协调者挂掉后参与者

无限阻塞和数据可能不一致的问题,但仍然没法解决网络分区的问题。

 

相对于上面两个协议,因为多数派的特性,paxos能够在节点失效、网络分区、网络延迟等各类异常状况下保证全部

节点都处于同一状态,它的结构图大体以下:

 

Basic paxos architecure.   A picutre  from:paxos-by-example

 

一个典型的paxos应用场景

 

分布式系统中有多个节点,通常每一个节点都是参与者,而其中一个节点既是参与者又是协调者。可是这样还会有单点

故障的问题,即若是协调者节点挂了,那么将没法进行任何事务,系统也就中止了正常运转。如何在还存活的其它节

点中选择一个来担当协调者的角色,使系统能够照常运行,达到山不转水转的目标呢?真的好难,可是有了paxos算

法,咱们能够解决这个难题。若是还以为这个问题抽象,那么能够换一种表述方式,即:如何在分布式系统中肯定某

一个变量的值。在这个具体的场景中,这个变量的值指定了哪一个节点将被选出来担当新协调者的角色。

 

paxos角色和规则

 

从上面的结构图中,咱们看到paxos主要涉及三个角色,分别为Acceptor、Proposer和Learner,在实践中,每每每一个节

点都具有这三个角色,这里为了让咱们大脑少些迷糊,暂且以每一个节点只具有一种角色来讨论。

 

paxos算法主要分为两个阶段:

 

1. Prepare:

 

Proposer 向全部Acceptor发送Prepare申请访问权,并携带一个提案号(epoch),Acceptor赋予访问权或拒绝,而且返回

该Acceptor 已经接受的值和对应的提案号。若是Proposer得到超过半数Acceptor的访问权,那么会进入第二阶段;

 

2. Accept:

 

1) 若是全部的Acceptor返回值都为空,则Proposer将携带本身预设的值v和本身的epoch号向获取到访问权的Acceptor发送请求;

2)若是Proposer第一阶段得到某些Acceptor的返回值不为空,则将epoch号最大的提案号对应的值f做为本身的预设值,和本身的

提案号一块儿向Acceptor发送请求(若是第一阶段返回f的Acceptor已经超过了半数,则表示已经造成肯定性取值,此时直接返回成

功,不须要进行Accept请求了);

 

对于Acceptor来讲,当它接收到Proposer请求时,须要应用一系列规则来决定如何响应,咱们对这些规则能够进行以下归纳:

 

1)喜新厌旧

当Acceptor接收到Prepare请求时,它将当前本身发放了访问权的epoch号和该Prepare请求携带的epoch进行比较,若是前者小

于后者,则将访问权赋予新请求的这个Proposer,不然拒绝发放访问权。这里咱们认为epoch值越大的越新。

 

2) 一视同仁

当Acceptor接收到Accept请求时,它 将当前本身发放了访问权的epoch号和该Prepare请求携带的epoch进行比较,若是前者大于

后者,则拒绝该请求。若是这两个epoch号相等, 而且Acceptor当前接受的取值为空,则接受该Acceptor请求,同时将该Accept

请求的值设置为接受值。若是以后又更大的epoch号申请 到访问权,并发出Accept请求,该值也不会改变,即Acceptor在肯定了

值以后再也不改变,谁先设置就用谁的值。虽然在发放访问权时是喜新厌旧,但 在取值这个问题上一视同仁,不会由于新epoch号

大而改变取值。这就像某些人,其余女人能够访问他,但老婆只要定了就不会变。

 

paxos正确性

 

假 设有N个Acceptor,多数派个数至少为N/2+1。若是有一个以上的Proposer获取到超过半数Acceptor的访问权,那么至少有一个

Acceptor是相同的。具体来讲,假设Proposer A在Prepare阶段获取到J个Acceptor的访问权,Proposer B在Prepare阶段获取到K个Acceptor的访问权,J>=N/2+1,K>=N/2+1,那么必然有这样一个Acceptor C,C既属于J又属于K,这种状况就是在C给某个Proposer发放访问权后,接着被另外一个Proposer抢占到了访问权时发生。 咱们假设Proposer A的取值为V1,Proposer B的取值为V2。在Accept阶段,对于Acceptor C来讲,它根据访问权来决定接受谁的Accept请求,若是当前是B得到了访问权,则接受B的取值V2,这样A在Accept阶段将失败,失败以后它可能 会继续生成新的epoch值从新进入Prepare阶段,可是这回它拿到了返回值V2,这样它以后进入Accept阶段时,会将V2做为它的取值向 Acceptor发送申请,最终Proposer A和Proposer B都达成了一致,即V2为最终取值。

 

以上是本人目前对paxos算法的一点理解,还将继续深刻和不断纠正.......

 

感受不错的资料,推荐参考:

 

前百度牛人李海磊的课程:

http://www.tudou.com/programs/view/e8zM8dAL6hM/

 

这个视频里还讲到了活锁,我看了启发不小:

https://www.youtube.com/watch?v=JEpsBg0AO

 

http://angus.nyc/2012/paxos-by-example/

 

http://blog.csdn.net/chen77716/article/details/6166675

相关文章
相关标签/搜索