Paxos算法是莱斯利·兰伯特(Leslie Lamport)于1990年提出的一种基于消息传递的一致性算法。 Paxos 算法是一个解决分布式系统中,多个节点之间就某个值(注意是某一个值,不是一系列值)达成一致的通信协议。能够处理在少数派离线的情况下,剩余的多数派节点仍然能够达成一致。 Lamport是通过故事的方式提出Paxos 问题:

  希腊岛屿Paxon 上的执法者在议会大厅中表决通过法律(一次paxos过程),并通过服务员(proposer)传递纸条的方式交流信息,每个执法者会将通过的法律记录在自己的账目上。问题在于执法者和服务员都不可靠,他们随时会因为各种事情离开议会大厅(服务器拓机或网络断开),并随时可能有新的执法者进入议会大厅进行法律表决(新加入机器),使用何种方式能够使得这个表决过程正常进行,且通过的法律不发生矛盾(对一个值达成一致)。 注意:paxos过程中不存在拜占庭将军问题(消息不会被篡改)和两将军问题(信道可靠)。 paxos 协议中有四种角色:

  client 议题产生者,产生一个待分布式系统达成一致的值v

  proposer 提议者,用client产生的值v,向acceptor发出提议

  acceptor 决策者,决定是否接受proposer的提议,大多数接受了提议,结果达成一致,达成一致的结果不可更改

  learner 决策学习者,学习最终达成一致的结果。一旦学习成功,关闭对应的paxos过程(paxos instance),并通知acceptor(或acceptor主动向learner获取)。

  这四种角色中,proposer和acceptor比较重要,协议主要的交互逻辑都在这两种角色中。

  paxos 是一个两阶段的通信协议:

  第一阶段 Prepare

  client产生一个值v,并告知proposer,我这里产生了一个待accept的值。

  proposer收到通知后,生成一个全局唯一并且递增的提案ID,带着这个ID(不需要携带v)向集群中的所有acceptor发送PrepareRequest请求。 acceptor收到PrepareRequest请求后,检查一下之前接收到的提案ID(包括第一阶段和第二阶段),新接收的提案ID用n表示,之前接收到的提案ID用N表示。如果n = N,返回拒绝,并携带N的值。如果n N,把n记录下来,以后不再接收提案ID比n小的提议,这时分两种情况:

  之前没有accept任何值v,返回可以接收提议

  之前已经accept过值,返回可以接收提议,并携带已经accept的,并且提案ID最大的值

  第二阶段 Accept

  如果proposer收到大多数acceptor的拒绝应答,回到第一阶段,根据接收到的最大的N,把提案ID增大,继续发送PrepareRequest。

  如果proposer收到大多数acceptor可以接收提议的应答,从多个应答中选出提案ID最大的值(第一阶段如果acceptor已经accept过值,会返回提案ID最大的值),作为提案值。如果应答中没有值,选择client产生的值v作为提案值。然后携带当前的提案ID,一起向集群中所有acceptor发送AccpetRequest请求。 对这段话进行解释:第一阶段client产生的值v,不一定作为Accept阶段的提案值。为了更快的达成一致,如果之前已经accept了值,那么proposer会倾向于把提案值修改为之前接受的值。各个proposer不是针锋相对,而是合作共赢。 acceptor收到AccpetRequest后,检查请求中携带的提案ID,如果此提案ID大于或等于acceptor记录的提案ID(在第一阶段和第二阶段,acceptor记录最大的提案ID),接受提议并记录提案ID和提案值。否则拒绝,并返回记录的提案ID。 proposer收到大多数acceptor接受提案的应答,形成决议,达成一致。

  如果proposer收到大多数acceptor拒绝的应答,回到第一阶段,把提案增大(增加幅度依据acceptor返回的提案ID),发送PrepareRequest。

  举个例子帮助理解paxos协议,把整个paxos协议的流程想象成一次竞标。有两个老板(client),每个老板都有一个属于自己的秘书(proposer),还有3个政府官员(acceptor)。

  第一阶段

  两个老板(client)分别提出议题:“XXX项目我要中标”,各自的秘书(proposer)带着现金(提案ID),去找政府官员(acceptor)。

  作为政府官员(acceptor),谁给的钱多答应给谁中标(只是口头答应,并没有签约)。钱少的直接拒绝。

  场景1:秘书p1带着10000美金去找3个官员a1、a2、a3,这时候还没有人来找过a1、a2、a3,所以这3个官员直接就答应了p1,并告诉p1他们之前没有接受过任何提议。这样p1在一阶段获得了全票支持。过一会,秘书p2带着8000美金去找3个官员,3个官员一看只有8000美金,直接拒绝p2,告诉p2别人已经出价10000。

  场景2:p1的行为和第一个场景相同。p2带着12000美金去找3个官员,3个官员一看p2给的钱比p1多,把p2的钱记下来,很高兴的告诉p2,可以接收p2的提议。这样在第一阶段p1和p2都获得了全票支持。

  场景3:p1和p2同时带着10000美金去找3个官员,p1先找到了a1、a2,此时没有人找过a1和a2,a1和a2答应p1,告诉p1他们之前没有接受过任何提议。p2在p1之前找到了a3,之前没有人找过a3,a3答应p2,告诉p2他之前没有接受过任何提议。这时候p1也找到了a3,a3一看和之前收到的钱一样多,拒绝了p1。同样,在p2找到a1和a2时,应为钱数一样,也被拒绝。最终,在第一阶段,p1获得2票(a1和a2),超过半数,p1可以进入第二阶段。p2获得1票,少于半数,p2被打回第一阶段。

  第二阶段

  场景1:在第一阶段p1获得了全票支持,p1带着老板的议题去找官员签合同,并告诉官员之前已经给了10000美金。官员看了一下收款记录,没错是10000美金,3个官员和p1成功签约,达成一致。在第一阶段p2被拒绝,这时p2回到第一阶段,带了12000美金去找官员。官员一看12000比刚才接受的10000多,告诉p2,你的钱多,可以接受你的议题,但是之前已经接受了p1的议题,p1的议题内容为“XXXXXX”。p2看了下p1的议题,觉得自己的老板没前途,干脆跟着p1的老板干算了,于是把自己的议题修改为p1的议题(为了更快达成一致)。p2带着修改之后的议题去找官员,告诉官员之前给了12000。官员看了一下记录,没错是12000,接受了p2的议题(这时p2的议题和p1一样,虽然官员同时接受了p1和p2,但是系统仍然是一致的)。

  场景2:在第一阶段p1获得了全票支持,p1带着老板的议题去找官员签合同,并告诉官员之前已经给了10000美金。官员看了一下收款记录,记录上写的是12000,于是告诉p1,已经有人出了12000,我们不能accept你的提议。在第一阶段p2也获得了全票支持,这时候p2来找官员,告诉官员之前给了12000,官员核实了一下记录,发现没错,接受了p2的议题。p1被拒绝后,回到第一阶段,带了14000美金去找官员。官员一看14000比刚才接受的12000多,告诉p1,你的钱多,可以接受你的议题,但是之前已经接受了p2的议题,p2的议题内容为“XXXXXX”。p1看了下p2的议题,觉得自己的老板没前途,干脆跟着p2的老板干算了,于是把自己的议题修改为p2的议题(为了更快达成一致)。p1带着修改之后的议题去找官员,告诉官员之前给了14000。官员看了一下记录,没错是14000,接受了p1的议题(这时p1的议题和p2一样,虽然官员同时接受了p1和p2,但是系统仍然是一致的)。

  场景3-1:在第一阶段p1获得a1、a2的应答,p1带着老板的议题去找a1、a2签合同,并告诉a1、a2之前已经给了10000美金。核实之后,a1和a2接受了p1的议题。由于大多数官员接受了p1的议题,所以p1的议题被确定接受。

  场景3-2:在第一阶段p1获得a1、a2的应答,p1带着老板的议题去找a1、a2签合同。但是p2在被打回第一阶段后,以很快的速度带着12000美金,赶在p1之前再次找到a1和a2以及a3。a1、a2、a3答应p2,并把记录金额修改为12000,并告诉p2,我们没有接受任何议题(p1还在签约途中)。这时p1终于找到了a1和a2,准备签约,但是a1和a2告诉p1,我们刚才收了12000,比你给的10000要多,拒绝接受你的议题,p1被打回第一阶段。在第一阶段p2获得全票,于是带着议题去找a1、a2、a3签约,a1、a2、a3核实金额之后,成功签约,达成一致。

  paxos协议中的活锁问题

  在上边描述的场景中,如果在官员签约之前,p1和p2一直不停的往上加金额,就算进入第二阶段,也会因为有更高的报价,导致签约失败被打回第一阶段。就像拍卖会中,多个买家一直往上飙价格,最后一件东西都没有卖出去。这种情况称为活锁,没有产生阻塞,但是一直无法达成一致。

  有三种解决方案:

  在被打回第一阶段再次发起PrepareRequest请求前加入随机等待时间。

  设置一个超时时间,到达超时时间后,不再接收PrepareRequest请求。

  在proposer中选举出一个leader,通过leader统一发出PrepareRequest和AcceptRequest。

  multi paxos

  一次paxos过程(paxos instance)只能对一个值达成一致。multi paxos是运行多个paxos instance来对多个值达成一致。

  下边以MySQL组复制为例,说明multi paxos。

  MySQL组复制中存在多个master,可以同时接受client写入和读取数据,并且可以保证多个master中数据一致,每一次写入数据都会生成一条log日志,通过paxos协议进行一致性处理,达成一致之后完成log复制。针对一系列操作,需要运行多次paxos过程(paxos instance),需要引入一个ID来标识相应的paxos instance,这里用logID表示。每一次写入操作,都生成一个logID与log日志对应,也同时与paxos instance对应,logID全局唯一且自增。

  有了logID之后,每个paxos instance独立运行,可以对每条log日志达成一致。这样问题貌似已经解决了,但是还有优化的空间。

  每一次paxos instance都是一个两阶段过程(prepare和accept),所有proposer地位平等,都可以提出议题。在有多个proposer同时提出议题时,有很大概率冲突,每次冲突都会重新执行prepare阶段,网络和性能开销较大。同时paxos协议本身存在活锁问题,有可能导致一个议题始终无法达成一致。为了解决这两个问题,multi paxos中引入了leader的概念,从多个proposer中选举出一个leader作为提议代表,每个提议都通过leader发出。这样的话,解决了活锁问题(活锁问题的第三个解决方案)。因为提议都是通过leader发出,只要leader保证提案ID自增,就可以跳过prepare阶段,直接进行accept阶段(两阶段变为一阶段)。

  那么问题来了,如何选举leader?运行一次paxos instance,提议的v就是“选举自己为leader”。但是还有问题,一次paxos instance只能对一个值达成一致。举个例子:A、B、C三台机器,运行paxos选举leader。第一次选举产生结果,A是leader。之后A拓机,再次运行paxos,选举的结果还是A是leader。运行多个paxos instance(multi paxos)可以选举出不同的leader,但是multi paxos需要选举出一个leader来优化网络损耗和活锁的问题,这里产生一个问题递归依赖。

  换个思路,给每一个达成一致的值v一个过期时间,达到过期时间清空v,这样用一个paxos instance就可以选出不同的leader。每台机器上都启动一个倒计时T,leader在存活状态下,不断重置T,T在倒计时为零时清空上次选举的结果,并发起选举。

  上边简单说明了一种选举leader的算法,通过选举leader,可以提高paxos的性能(两阶段变为一阶段),并解决活锁问题。paxos的正确性不依赖于选举结果,在选举失败或者同时选出多个leader的情况下,退化为普通paxos。

  总结

  paxos协议可以归纳为几个原则:

  不接受旧值(通过递增ID确定新旧)

  为了更快达成一致,proposer会把值修改为最有可能达成一致的值

  只有多数派接受了值,值才达成一致

  一旦一个值达成一致,不可更改

  paxos是一致性协议的基础,其他的协议(raft、zab等)都是paxos的改进版本。paxos侧重理论,实现paxos非常困难。谷歌chubby论文中提到,从paxos出发,在实现过程中处理了很多实际中的细节之后,已经变成另外一个算法了,这时候正确性无法得到理论的保证。所以才出现了许多基于paxos的改进算法。

分布式系统理论:一致性协议Paxos的更多相关文章

  1. 五:分布式事务一致性协议paxos的应用场景

    1.应用场景 (1)分布式中的一致性 Paxos算法主要是解决一致性问题,关于“一致性”,在不同的场景有不同的解释: NoSQL领域:一致性更强调“能读到新写入的”,就是读写一致性数据库领域:一致性强 ...

  2. 六:分布式事务一致性协议paxos的分析

    最近研究paxos算法,看了许多相关的文章,概念还是很模糊,觉得还是没有掌握paxos算法的精髓,所以花了3天时间分析了libpaxos3的所有代码,此代码可以从https://bitbucket.o ...

  3. 四:分布式事务一致性协议paxos通俗理解

    转载地址:http://www.lxway.com/4618606.htm 维基的简介:Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的"La" ...

  4. [转帖]图解分布式一致性协议Paxos

    图解分布式一致性协议Paxos https://www.cnblogs.com/hugb/p/8955505.html   Paxos协议/算法是分布式系统中比较重要的协议,它有多重要呢? <分 ...

  5. [从Paxos到ZooKeeper][分布式一致性原理与实践]<二>一致性协议[Paxos算法]

    Overview 在<一>有介绍到,一个分布式系统的架构设计,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是产生了一系列的一致性协议. 为解决分布式一致性问题,在长期的探索过程中 ...

  6. 三:分布式事务一致性协议2pc和3pc

    一:分布式一致性协议--->对于一个分布式系统进行架构设计的过程中,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是就产生了一系列的一致性协议.--->长期探索涌现出一大批经典的一 ...

  7. [转]图解分布式一致性协议Paxos

    Paxos协议/算法是分布式系统中比较重要的协议,它有多重要呢? <分布式系统的事务处理>: Google Chubby的作者MikeBurrows说过这个世界上只有一种一致性算法,那就是 ...

  8. 图解分布式一致性协议Paxos

    Paxos协议/算法是分布式系统中比较重要的协议,它有多重要呢? <分布式系统的事务处理>: Google Chubby的作者Mike Burrows说过这个世界上只有一种一致性算法,那就 ...

  9. 分布式一致性协议 --- Paxos

    问题 Paxos 到底解决什么样的问题,动机是什么 Paxos 流程是怎么样的? Paxos 算法的缺陷是什么 概述 Paxos 是分布式一致性算法,根据少数服从多数的原则多个节点确定某个数值.通过学 ...

随机推荐

  1. Flume 1.7 源代码分析(四)从Source写数据到Channel

    Flume 1.7 源代码分析(一)源代码编译 Flume 1.7 源代码分析(二)总体架构 Flume 1.7 源代码分析(三)程序入口 Flume 1.7 源代码分析(四)从Source写数据到C ...

  2. 目标检测-Faster R-CNN

    [目标检测]Faster RCNN算法详解 Ren, Shaoqing, et al. “Faster R-CNN: Towards real-time object detection with r ...

  3. SSH三大框架的搭建整合(struts2+spring+hibernate)

    本文转载自:https://blog.csdn.net/kyle0349/article/details/51751913

  4. 对BeforeSuite和BeforeTest的理解

    在BeforeSuite.BeforeTest.BeforeClass.BeforeMethod及BeforeGroups中,后面三个注解都比较好理解,其实BeforeSuite.BeforeTest ...

  5. Html5实现iPhone开机界面

    今天我突发其想,想到可以用HTML5来仿照苹果操作系统做一个能在Web平台运行的iOS. 当然,要开发出一个操作系统,等我再归山修练一百年再说吧.今天就先娱乐一下,先搞一个开机界面. 完工后的图片: ...

  6. jQuery异步加载数据并添加事件示例

    当时项目是通过树形栏进行权限控制的,管理员可以对从数据库去的数据动态生成树形栏进行增删改查操作,可是用$(".XX").click();方法是不行的. 1.之前用的是jq1.4.3 ...

  7. Angular 笔记系列(二)数据绑定

    数据绑定这块儿没啥说的,简单两个例子带过了. Hello World: <!DOCTYPE html> <html ng-app> <head> <title ...

  8. linux用户 群组权限

    用户及passwd文件 /etc/passwd文件的功能 /etc/passwd文件每个字段的具体含义 shadow文件 /etc/shadow文件的功能 /etc/shadow文件每个字段的具体含义 ...

  9. SQL Server排名函数与排名开窗函数

    什么是排名函数?说实话我也不甚清楚,我知道 order by 是排序用的,那么什么又是排名函数呢? 接下来看几个示例就明白了. 首先建立一个表,随便插入一些数据. ROW_NUMBER 函数:直接排序 ...

  10. OpenStack之Neutron网络服务(一)

    1.Neutron概要 OpenStack网络服务提供了一个API接口,允许用户在云上设置和定义网络连接和地址.这个网络服务的项目代码名称是Neutron.OpenStack网络处理虚拟设备的创建和管 ...