原文:https://www.quora.com/Distributed-Systems/What-is-a-simple-explanation-of-the-Paxos-algorithm

作者:Vineet Gupta, Ships software

我想在一些尝试解决达成共识问题的案例中理解Paxos会比较容易,但也有不足之处,让我们讨论一下Paxos吧。

对达成共识这个词语的直观理解是结婚宣誓:

  • “Do you …?” “I do!” “I do!”
  • “I now pronounce you …”

假定现在婚礼限定只是两个人,而是像电视连续剧Robert Jordan’s Wheel中的 Aiel 人,一个或多个 Aiel 女人可以是 first-sisters ,一个男人要么娶了全部姐妹,要么一个都不能娶。对于 Aiel来说,婚礼宣誓的场景就变成这样了:

  • “Do you …?” “I do!” “I do!” “I do!” …
  • “I now pronounce you …”

如果有任何一个 Aiel 姐妹不回答 “I do!” ,婚礼就无法进行了。

计算机科学领域将这种情况称为二段提交。

二段提交 (2PC)

  1. 投票阶段 – 一个协调者提交一个值给所有节点,然后收集所有节点的反馈 (无论它们是否同意这个值)。在我们的场景中,一个事务的协调者询问是否所有的资源管理者 (数据库服务实例,以下简称RMs )可以提交事务。 RMs回复 yes 或者 no.
  2. 提交阶段 - 如果所有参与者同意, 协调者联系所有节点让他们知道这个值是最终的值。如果有任何一个节点不同意,通知所有节点这个值不是最终值。在我们的场景中,协调者询问RMs提交或者终止事务。

注意投票只真的提议的值 – 参与者节点只能说 yes 或者 no,它不能提议其它值。如果一个节点像提议一个值,那么它应该自己开启的二段提交过程。很明显这个算法可以起作用 – 参与者决定是否同意协调者提议的值。而且这个算法也没没那么低效率 – 对于 N 个节点, 只需要进行3N次通讯。

但如果其中一个节点死机了怎么办?例如,假设协调者在第一阶段的时候死机了,提议的值已经发送到了其中一些参与者那里,但还没发送到全部参与者。

  • 现在一些节点已经开始二段提交进程了,但仍然有一些节点还没有收到任何信息,没有参与到二段提交当中。
  • 在我们的场景中,一个 RM 可能已经投完票了,然后锁定了一些资源等待下一步操作,可能会一直处于等待当中,等待协调者随时会恢复正常时继续第二阶段的操作。

如果协调者在第二阶段的时候给部分参与者发送完提交命令后死机,也会有类似的问题。如果有其它节点检测超时然后接手协调者的工作,这个资源一直锁定等待的问题是可以解决的。这个节点可以和所有其它节点联系,从而发现它们的投票结果 (需要节点们持久化投票结果) 然后接手继续完成事务,但进一步参与者的失败可能会发生在此过程中,这样的话事务就永远不会恢复了。 最后结论 – 二段提交在节点失效时不具备可靠性。

三段提交 (3PC)
二段提交的关键问题是一旦协调者死掉了,没有任何参与者有足够能力来继续完成事务。这个问题可以通过增加一个额外的步骤来解决:

  1. 第一阶段 – 和以前一样 – 一个协调者向所有参与者提议一个值
  2. 第二阶段 – 这是新加进来的阶段 – 在上一个步骤接收到所有参与者回复 yes 之后,协调者发送一个准备提交的消息。参与者可以执行数据更新操作了,但是这是要保证这些更新对外不可见,即未提交状态,而且可以随时回滚
  3. 第三阶段 – 类似二段提交的第二阶段 – 如果协调者接收到所有的参与者的对“准备提交”命令的确认消息后,协调者就可以向所有参与者发送提交命令了。但是如果收不到所有参与者的对准备提交命令的确认消息,那么协调者就终止事务。

现在如果协调者死机了,任何参与者都可以接手它的工作,查询所有节点的状态,继续进行事务

  • 如果任何 RM 向新接手的协调者报告自己没有收到 “准备提交” 命令,那么新的协调者就可以知道事务还没有开始提交。现在事务不能永久地终止也不能重新开始新的事务。
  • 如果一个已经提交事务的 RM 死掉了,我们知道其它 RM 已经接收和承认 “准备提交”命令,否则协调者不会到达提交阶段。所以协调者可以继续发送提交命令。

所以三段提交可以工作得很好,除了没提交的节点操作失败的情况。当然,增加一个阶段会导致更多得通讯延迟。

在网络分隔的情况下(例如:一个集群两拨服务器之间通讯中断,会形成两个集群,可以说是脑裂)。假如所以接收到 “准备提交”命令的RM在其中一拨,另外的RM在另外一拨。现在每一拨RM各自选出新的协调者,就有两个协调者,如果一个协调者提交了事务,另外一个协调者终止了事务,那么当网络分隔取消的时候一拨RM提交了事务,另外一拨RM取消了事务,这样就造成了不一致的状态。

Paxos - 为什么要用Paxos?
第一 – 除了三段提交我们还有什么更好的方法吗?唯一的问题是网络分隔,是吧?为了开始,让我们假设网络分隔是唯一的问题(事实上这不是唯一的问题,等一下我们会提到)。网络分隔的问题是否值得去解决?今天,云计算和英特网范围的服务,不同的服务器之间可能跨洋跨大陆,我们需要一个分区容忍性算法。

第二点网络分隔不是唯一的问题。 当我们着手处理阶段永久失败的情况,最常见的情况是服务器死机,然后从死掉的地方重新恢复。这种失败-恢复模型也可以描述一个节点回应消息无时间上限的异步网络模型,因为你不能假设一个节点死掉了 – 它们可能只是慢一点或者网络慢一点。在这个模型,你不能设置超时。

三段提交是失败-停止,但不是失败-恢复。不幸的是真实的需求往往要求失败-恢复,因此我们需要更通用的解决方案。这就是Paxos协议诞生的原因

Paxos – 实现原理
在Paxos中,最基本的步骤很像二段提交:

  • 选择一个节点作为提议者
  • 提议者选择一个值,然后发送给所有接受者。接受者可用回复拒绝或接受
  • 一旦大多数节点接受提议,共识就达成了,协调者向所有接受者发送提交命令

和二段提交主要的不同是,不像二段提交需要所有节点同意,这样只需要大多数节点同意即可。这是个有趣的想法。这保证了在一个回合内,如果大多数节点同意了一个值,而后的任意节点尝试提议一个值的时候都会学习大多数节点同意的那个值。这也意味着 Paxos 不会阻塞,即使一小半节点响应失败。
当然协调者本身也可能失败。为了处理这个问题, Paxos 不会只指定一个协调者那么简单。它允许任何节点都可以成为协调者。两个协调者可能提议不同的值,那么怎么协调达成共识呢?为了解决共识达成一致的问题 Paxos 引入了两个机制:

  • 分配一个序列号给协调者。 不同协调者的序列号不同,这样可以防止旧的协调者 (例如从失败中恢复过来的协调者) 对达成的共识有异议。
  • 限定协调者的选值。一旦共识达成,Paxos 强制让后来的协调者选择已有的值,保证共识延续。这个可以通过让参与者发送自身同意的最新的值以及协调者的序列号来获得。新的协调者可以选择选择参与者返回的其中一个值,当没有任何参与者返回值的时候,就选择自己的值。

协议的步骤:

1) 准备阶段

  • 一个节点选择成为一个协调者,然后选择了一个序列号 x 和一个值 v 来建立一项提议 P1(x, v)。 它将这个提议发送给所有参与者,然后等待大多数参与者的响应。
  • 参与者接收到了提议 P1(x, v1) ,然后做如下事情:
    • 如果收到的是第一个提议,就回复 ‘agree’ – 它承诺会拒绝后来序列号 < x的所有请求
    • 如果已经同意过某个提议:
      • 将 x 和它同意过的最大的序列号的提议 P2(y, v2)对比
      • 如果 x < y, 回复 ‘reject’ 和 y
      • 如果 x > y, 回复 ‘agree’ 和 P2(y, v2)

2) 接受阶段

  • 如果大多数参与者失败或者回复拒绝,协调者会抛弃提案然后重新开始
  • 如果大多数参与者回复“同意”, 协调者也会接收到它们收到的提议的值。协调者拿到这些值任意一个 (如果还没有值被接受就用它自己的值) 然后发送一个“请接受我”的请求,这个请求会带上一个序列号和一个要提议的值。
  • 当参与者接收到一个“接受请求”的消息,当满足下面的两个条件的时候,它会发送一个‘接受’ 消息, 否则会发送一个拒绝消息:
    • 值和之前接受的任意值相同
    • 序列号是参与者所接受所有值的最大值
  • 如果协调者没有得到大多数参与者 ‘接受’ 的消息,它的提议将会被摒弃,重新开始一次事务。然而如果协调者没有得到大多数参与者的“接受”,事务可以终止了。为了优化,协调者可能发送 ‘提交’ 命令给其它节点

Paxos 处理失败
如果授权时Paxos只有一个协调者, 用授权来代替投票,所有节点都必须投票吗?你猜对了 – 二段提交就是这样的。 二段提交是Paxos的某个特殊情况。

如你所见, Paxos  比二段提交有更高的失败容忍性:

  • 协调者失败 – 另外一个协调者可以代替它,提出自己的提议。
  • 原来的协调者恢复 – 两个协调者可以同时存在,多亏了这个规则:只同意最大的序列号以及只能提交前一个同意的值

Paxos也比三段提交更具有容错性。特别地,Paxos的分区容忍性不同于三段提交。在三段提交,如果两个隔离的分区同意了一个值,当分区合并的时候,就会出现违反一致性的情况。在Paxos,这种情况是不会出现的,因为有大多数选票机制。除非一个分区有大多数参与者同意,否则不会达成一致。如果一个分区有大多数参与者同意能够达成一致,这个值会被其它分区采取。

Paxos的一个问题是两个协调者,不能互相观察,当有分区隔离的时候,可能会尝试提出一个比前一个提议更高的序列号的提议。这会导致Paxos事务永远不会休止(成为活锁)。尽管两个协调者期望观察另外一个,并且其中一个需要退出。

这是个安全和可用性之间的平衡。Paxos是一个安全的算法 – 一旦共识达成,被同意的值不会改变。然而 Paxos不保证可用性 – 在某些很少的情况下它会终止。事实上一个异步的一致性算法不能同时保证安全和可用性,这被称为 FLP 不可能结果.

译者注:已经翻译完毕,但可能存在翻译语言生硬、可读性和可理解性差等问题,以后有时间再完善,谢谢关注。

进一步阅读

    • Principles of Transaction Processing, Chapter 8 provides a detailed overview of the Two Phase Commit
    • Non-blocking Commit Protocols - original paper by Dale Skeen that describes 3PC
    • The Part-time Parliament – the original Paxos paper by Lamport. It uses a parliament analogy which people found hard to get past when the paper was originally published.
    • Paxos Made Simple – the rewrite by Lamport without the Parliament analogy. While simple, one can miss the forest for the trees. Requires multiple readings to grok.
    • Paxos Made Live – Google’s description of their Paxos implementation. The most readable of the Paxos papers.

分布式系统:怎么简单地解释Paxos算法?从二段提交、三段提交讲到Paxos的更多相关文章

  1. 分布式数据库中的Paxos 算法

    分布式数据库中的Paxos 算法 http://baike.baidu.com/link?url=ChmfvtXRZQl7X1VmRU6ypsmZ4b4MbQX1pelw_VenRLnFpq7rMvY ...

  2. Paxos 算法

    1 概述 Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的"La",此人现在在微软研究院)于1990年提出的一种基于消息传递的一致性算法.[1] ...

  3. Paxos算法(转)

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

  4. Paxos算法小结

    转自不正直的绅士,因百度空间迁移,无法注明出处,我从其google搜索引擎中的cache进行的copy. 不正直的绅士 是跟我一起工作过的非常有才的一个青年才俊. Paxos的使用非常广泛.sanlo ...

  5. 从分布式一致性到共识机制(一)Paxos算法

    从分布式系统的CAP理论出发,关注分布式一致性,以及区块链的共识问题及解决. 区块链首先是一个大规模分布式系统,共识问题本质就是分布式系统的一致性问题,但是又有很大的不同.工程开发中,认为系统中存在故 ...

  6. Paxos 算法 :消息传递一致性

    网络上有很多关于优秀的关于Paxos 算法的文章,我下面进行整理搜集一下: 分布式理论之一:Paxos算法的通俗理解 维基的简介:Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 L ...

  7. 深入研究Paxos算法原理

    一.Paxos算法产生的背景 Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一,其解决的问题就是在分布式系统中如何就某个值(决议)达成一致. ...

  8. 分布式技术专题-分布式协议算法-带你彻底认识Paxos算法、Zab协议和Raft协议的原理和本质

    内容简介指南 Paxo算法指南 Zab算法指南 Raft算法指南 Paxo算法指南 Paxos算法的背景 [Paxos算法]是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息 ...

  9. [转] Paxos算法2-算法过程(实现)

    请先参考前文:Paxos算法1 1.编号处理 根据P2c ,proposer在提案前会先咨询acceptor查看其批准的最大的编号和value,再决定提交哪个value.之前我们一直强调更高编号的pr ...

  10. Zookeeper笔记(二)Paxos算法与Zookeeper的工作原理

    Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管 ...

随机推荐

  1. rabbitmq

    send端 import pika credentials = pika.PlainCredentials(') connection = pika.BlockingConnection(pika.C ...

  2. 《Linux常用命令》笔记

    ① ifconfig 查看IP状态; ② ls 查看当前路径文件信息,参数: -l 查看文件的详细信息与ll效果一样; -a 查看文件的全部信息; ③ man 查询当前指令的信息,查询可用字母q退出; ...

  3. linux c/c++

    string 字符串操作 操作数的都是 ( char * )型,操作数必须是指向字符串的指针("a"),不能是字符('a'),操作时不考虑末尾的'\0'. size_t strle ...

  4. WPF去边框与webbrowser的冲突

    首先建一个类,比如NativeMethods.cs class NativeMethods{     public const int WS_CAPTION=0x00C0000;     public ...

  5. 如何在Linux中搭建禅道8.4.1(httpd+php+mysql)

    1.安装httpd 命令:yum install httpd 然后一路y即可 2.安装php 命令:yum install php   3.安装php-mysql 命令:yum install php ...

  6. 使用java读取文件夹中文件的行数

    使用java统计某文件夹下所有文件的行数 经理突然交代一个任务:要求统计某个文件夹下所有文件的行数.在网上查了一个多小时没有解决.后来心里不爽就决定自己写一个java类用来统计文件的行数,于是花了两个 ...

  7. Tomcat7.0+ web.xml问题

    Tomcat7+版本的web.xml都加上 <context-param> <param-name>webAppRootKey</param-name> <p ...

  8. html内的空格占位

    写html的时候有时因为字数不够会根据字段长度添加多个空格,但是在html中添加空格是没有用的,所以使用空格的代替符号有:   不断行的空白(1个字符宽度)   半个空白(1个字符宽度)   一个空白 ...

  9. ATM+购物车

    本次代码的实现用到了模块间的互相调用,这对于初学者而言有些难度,不过这也是我们必须要掌握的,在以后的大程序中,多个模块会让我们的代码看起来简洁明了,易排错 (本次代码只是简单的实现的基本的功能,其代码 ...

  10. 【DWR系列04】- DWR配置详解

    table { margin-left: 30px; width: 90%; border: 1px; border-collapse: collapse } img { border: 1px so ...