分布式一致性协议之:Paxos算法(转)

 Paxos算法的难理解与算法的知名度一样令人敬仰,从我个人的经历而言,难理解的原因并不是该算法高深到大家智商不够,而在于Lamport在表达该算法时过于晦涩且缺乏一个完整的应用场景。如果大师能换种思路表达该算法,大家可能会更容易接受:

  • 首先提出算法适用的场景,给出一个多数读者能理解的案例
  • 其次描述Paxos算法如何解决这个问题
  • 再次给出算法的起源(就是那些希腊城邦的比喻和算法过程)

Lamport首先提出算法的起源,在没有任何辅助场景下,已经让很多人陷于泥潭,在满脑子疑问的前提下,根本无法继续接触算法的具体内容,更无从体会算法的精华。本文将换种表达方法对Paxos算法进行重新描述。

我们所有的描述都假设读者已经熟读了Lamport的paxos-simple一文,因此对各种概念不再解释。

除了Lamport的几篇论文,对Paxos算法描述比较简洁的中文文章是:http://zh.wikipedia.org/zh-cn/Paxos%E7%AE%97%E6%B3%95,该文翻译的比较到位,但在关键细节上还是存在一些歧义和一些对原文不正确的理解,可能会导致读者对Paxos算法更迷茫,但阅读该文可以快速地对Paxos算法有个大概的了解。

 

1.应用场景

 

(1)分布式中的一致性

Paxos算法主要是解决一致性问题,关于“一致性”,在不同的场景有不同的解释:

  • NoSQL领域:一致性更强调“能读到新写入的”,就是读写一致性
  • 数据库领域:一致性强调“所有的数据状态一致”,经过一个事务后,如果事务成功,所有的表数据都按照事务中的SQL进行了操作,该修改的修改,该增加的增加,该删除的删除,不能该修改的修改了,该删除的没删掉;如果事务失败,所有的数据还是在初始状态;
  • 状态机:在状态机中的一致性更强调在每个初始状态一致的状态机上执行一串命令后状态都必须相互一致,也就是顺序一致性。Paxos算法中的一致性指的就是这种情况,接下来我们会对这种场景进一步讨论。

(2)MQ

假如所有系统的Log信息都写入一个MQ Server,然后通过MQ把每条Log指令发异步送到多个Log Server写入文件(写入多个Log Server的原因是对Log文件做备份以防数据丢失),则所有Log Server上的数据肯定是一致的(Log内容及顺序完全相同),因为MQ本身就有排序功能,只要进了Q数据也就有了序,相当于编了全局唯一的号,无论把这些数据写入多少个文件,只要按编号,各文件的内容必定是一致的,但一个MQ Server显然是一个单点,如果宕机,会影响整个系统的可用性。

 

(3)多MQ

要解决MQ单点问题,首选方案是采用多个MQ Server,即使用一个MQ Cluster,客户端可以访问任意MQ Server,不同的客户端可能访问不同MQ Server,不同MQ Server上的数据内容、顺序可能不一致,如果不解决这个问题,每个MQ Server写入Log Server的内容就不一致,这显然不是我们期望的结果。

 

(4)NoSQL中的数据更新

一般的NoSQL都会通过数据复制的形式保证其可用性,但客户端对多数据进行操作时,可能会有很多对同一数据的操作发送的某一台或几台Server,有可能执行:Insert、Update A、Update B....Update N,就一次Insert连续多次Update,最终复制Server上也必须执行这一的更新操作,如果因为线程池、网络、Server资源等原因导致各复制Server接收到的更新顺序不一致,这样的复制数据就失去了意义,如果在金融领域甚至会造成严重的后果。

 

上面这些不一致问题性正是Paxos算法要解决的,当然这些问题也不是只有Paxos能解决,在没有Paxos之前这些问题也得到了解决,比如通过使用双Master模式的MQ解决MQ单点问题;通过使用Master Server解决NoSQL的复制问题,但这些解决方法都存在一些缺陷,要么难水平扩展,要么影响可用性。当然除了Paxos算法还有其他一些算法也试图解决这类问题,比如:Viewstamped Replication算法。

 

上面描述的这些场景的共性是希望多Server之间状态一致,也就是一致性,再看中文Wiki开篇提到的:

在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致

大家或许会对该描述有更深的理解。

 

2.Paxos如何解决这类问题

paxos算法是由大牛lamport发明的,关于paxos算法有很多趣事。比如lamport论文最初由故事描述来引入算法,以至于那班习惯数学公式的评委将该论文打回,导致该论文延误了8年才公开发表。另外,google的chubby的作者Mike Burrows说过,世界上只有一种一致性算法,那就是paxos。

两将军问题

为了引入该算法,首先提出一种场景,即两将军问题(见文献1):

 

[plain] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. 有两支军队,它们分别有一位将军领导,现在准备攻击一座修筑了防御工事的城市。这两支军队都驻扎在那座城市的附近,分占一座山头。一道山谷把两座山分隔开来,并且两位将军唯一的通信方式就是派各自的信使来往于山谷两边。不幸的是,这个山谷已经被那座城市的保卫者占领,并且存在一种可能,那就是任何被派出的信使通过山谷是会被捕。 请注意,虽然两位将军已经就攻击那座城市达成共识,但在他们各自占领山头阵地之前,并没有就进攻时间达成共识。两位将军必须让自己的军队同时进攻城市才能取得成功。因此,他们必须互相沟通,以确定一个时间来攻击,并同意就在那时攻击。如果只有一个将军进行攻击,那么这将是一个灾难性的失败。  

两将军问题本质上就是通信被篡改时能否解决一致性问题。这个问题已经被很多人证明不能。(见文献1)。因而由此推及的拜占庭将军问题(多将军问题)也同样不能被解决。

 

PAXOS算法

 

[html] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. 一个叫做Paxos的希腊城邦,这个岛按照议会民主制的政治模式制订法律,但是没有人愿意将自己的全部时间和精力放在这种事情上。所以无论是议员,议长或者传递纸条的服务员都不能承诺别人需要时一定会出现,也无法承诺批准决议或者传递消息的时间。但是这里假设没有拜占庭将军问题(Byzantine failure,即虽然有可能一个消息被传递了两次,但是绝对不会出现错误的消息);只要等待足够的时间,消息就会被传到。另外,Paxos岛上的议员是不会反对其他议员提出的决议的。  

这里不再赘述算法的推导及证明过程,参考文献2和3。这里简单描述下算法理解。

基本思想也是两阶段提交。但是与两阶段目的不同。

1. 第一阶段主要目的是选出提案编号最大的proposer。

其描述如下,所有的proposer向超过半数的acceptor提出编号为n的提案,acceptor收到编号为n的请求,会出现两种情况

a. 编号n大于所有acceptor之前已经批准过的proposal的最大编号及内容m。acceptor同意该proposal,响应[n, m]回proposer,并且承诺今后不再批准任何编号小于n的提案。

b. 编号n小于acceptor之前批准过的任意proposal的编号。acceptor拒绝该proposal。

2. 第二阶段尝试对某一proposal达成一致。
proposer收到超过半数的acceptor返回的响应,proposer就会将响应的最大编号[n, m]对应的提案提交到acceptor要求acceptor批准该提案。

acceptor收到最大编号[n, m]的提案,也分为两种情况

a. 未响应过编号大于n的prepare请求。通过该提案。

b. 已响应过编号大于n的prepare请求。拒绝该提案。

整个算法表面上并不难理解,难在实现细节的难易程度和各种异常情况的推导及考虑。如果对上述算法有理解困难的,参考文献4和文献5的例子,其中文献5更容易理解,这里 把他的图贴出来,实际过程就不再重复赘述了。

两个参谋先后提议的场景

两个参谋交叉提议的场景

需要注意的是参谋1在失败时再次发起请求的过程

 

这里着重强调几个重点。

1. 算法描述里有好几个地方要求投票必须超过半数,这个超过半数恰恰是保证一致的一个必要条件

2. 算法里也有多处要求只选择编号最大的,这种选择编号最大的方式,是一种最为简单经济的达成共识的方法,能够快速在多个冲突中找到一个突破口

3. paxos算法的关键是,如果一个值m被选中了,那么必须保证更高的proposal其值也为m

4. 注意第一阶段比较的是已经批准过的proposal的最大编号,而第二阶段比较的是prepare请求。即第一阶段比较的是第二阶段的结果,而第二阶段比较的是第一阶段的结果,看似很绕,实际上正好是隔离了阶段外的保证,进入第一阶段的我要保证他是新的开始,跟上一阶段没啥关系,而进入第二阶段的我要保证他是从前面阶段来的,而不是新起的一个阶段,有点像是隔离锁,锁住了阶段一到阶段二这个过程。

 

分布式系统的事务处理  http://coolshell.cn/articles/10910.html

paxos wiki https://en.wikipedia.org/wiki/Paxos_(computer_science)

paxos维基 https://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95

paxos算法例子 https://www.zhihu.com/question/19787937/answer/107750652

paxos算法例子2* http://iunknown.iteye.com/blog/2246484?from=message&isappinstalled=0

Paxos算法1-算法形成理论 http://blog.csdn.net/chen77716/article/details/6166675

posted on 2014-06-13 18:01  duanxz  阅读(623)  评论(0编辑  收藏  举报