聊聊分布式一致性算法协议 Paxos

8e1ec8b95ada442f7d70c6edda876667.gif

作者 | 码哥字节

来源 | 码哥字节

Google的粗粒度锁服务Chubby的设计开发者Burrows曾经说过:所有一致性协议本质上要么是Paxos要么是其变体。

网上有很多讲解Paxos算法的文章,但是质量层次不齐。今天笔者带大家深入聊一下Paxos

Paxos是什么?

Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。

Paxos算法是Lamport宗师提出的一种基于消息传递的分布式一致性算法,使其获得2013年图灵奖。

自Paxos问世以来就持续垄断了分布式一致性算法,Paxos这个名词几乎等同于分布式一致性。

Google的很多大型分布式系统都采用了Paxos算法来解决分布式一致性问题,如Chubby、Megastore以及Spanner等。开源的ZooKeeper,以及MySQL 5.7推出的用来取代传统的主从复制的MySQL Group Replication等纷纷采用Paxos算法解决分布式一致性问题。

但是它也有两个明显的缺点:

  1. 难以理解

  2. 在工程是实现上比较复杂。

问题产生的背景

在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。

这里某个数据的值并不只是狭义上的某个数,它可以是一条日志,也可以是一条命令(command)。根据应用场景不同,某个数据的值有不同的含义。

d7f65a7ae4036a5befbbf1dc90904208.png

相关概念

在Paxos算法中,有三种角色:

  • Proposer (提案者)

  • Acceptor (人大代表)

  • Learners (广大群众)

需要注意的是,在具体的算法实现过程中,并不是一个进程只能担任其中一种角色,它有可能会同时充当多个。比如一个进程既是Proposer又是Acceptor还是Learner。

还有一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里。

这个提案包括什么呢?是仅仅包括一个信息数值吗?到底是如何咱们继续向下阅读,目前咱们先认为仅仅是一个普普通通的value。

b636c46744f97e044ecc3c00554235ab.png

初次认识

Paxos算法过程和我国的立法过程是极其相似的(法律案的提出、法律案的审议、法律案的表决、法律的公布四个阶段),所谓的提案就是新颁布法律。

Proposer (提案者)可以提出(propose)提案;Accoptor可以接受(accept)提案;如果某个提案被选定(chosen),那么该提案里的value就被选定了。

回到刚刚说的『对某个数据的值达成一致』,指的是Proposer、Acceptor、Learner都认为同一个value被选定(chosen)。那么,Proposer、Acceptor、Learner分别在什么情况下才能认为某个value被选定呢?

  • Proposer:只要Proposer发的提案被Acceptor接受(刚开始先认为只需要一个Acceptor接受即可,在推导过程中会发现需要半数以上的Acceptor同意才行),Proposer就认为该提案里的value被选定了。

  • Acceptor:只要Acceptor接受了某个提案,Acceptor就认为该提案里的value被选定了。

  • Learner:作为一个学习者,Acceptor告诉Learner哪个value被选定,Learner就认为那个value被选定。

问题描述

假设有一组可以提出(propose)value的进程集合(提案者团队),一个一致性算法需要保证提出的这么多value中,仅仅只有一个相同的value被选定(chosen)。也就是说要么没有value被提出,只要提出了value并且被选定,那么大家最终学习到的value必须是一致的。对于一致性算法,安全性(safaty)要求如下:

  • 只有被提出的value才能被选定。

  • 只有一个value被选定。

  • 如果某个进程认为某个value被选定了,那么这个value必须是真的被选定的那个。

Paxos的目标:保证最终有一个value会被选定,当value被选定后,进程最终也能获取到被选定的value。

俗话说的好,哪里有需求,哪里就会出现糟糕的问题。如果假设不同角色之间可以通过发送消息来进行通信,那么:

  • 每个角色以各自任意的速度进行通信执行,在这个过程中可能会因为各种原因出错而导致执行停止或重启。当一个value被选定之后,因为故障原因才恢复正常的角色因为失去了某些重要的信息,导致它们无法确定被选定的值。

  • 消息在传递过程中可能出现任意时长的延迟,可能会重复,也可能丢失。但是消息不会被损坏,即消息内容不会被篡改(拜占庭将军问题)。

以上都是可能会遇到的问题,要怎么解决???

推导过程

最简单的方案——只有一个Acceptor

假设只有一个Acceptor(可以有多个Proposer),只要Acceptor接受它收到的第一个提案,则该提案被选定,该提案里的value就是被选定的value。这样就保证只有一个value会被选定。

但是,如果这个唯一的Acceptor宕机了,那么整个系统就无法工作了!

因此,一个Acceptor是不可行的,必须要有多个Acceptor!

b6dbddf9645168fe2e9a4fac9e13dffe.png

多个Acceptor

当有多个Acceptor的时候,如何保证在多个Proposer和多个Acceptor的情况下选定一个value呢?

大家可以自己先进行思考。

首先,我们的最终目标是无论有多少Proposer提出提案,有且仅有一个value被选定。

那么,我们可以先定义一个约束:

P1:一个Acceptor必须接受它收到的第一个提案。

但是,这样又会出现其它的问题:如果每个Proposer所提出的提案value是不同的,并且将提案发送给不同的Acceptor。根据P1约束,每个Acceptor都接受它收到的第一个提案,就会出现不同value被选定的情况,出现了不一致。

6f3ba6b6698519d8b16967849711c61d.png

刚刚是因为『一个提案只要被一个Acceptor接受,则该提案的value就被选定了』才导致了出现上面不一致的问题。因此,我们需要加一个规定:

规定:一个提案被选定需要被半数以上的Acceptor接受

一个提案被半数以上接受,说明『一个Acceptor必须能够接受不止一个提案!』,不然可能导致最终没有value被选定。比如上图的情况。v1、v2、v3都没有被选定,因为它们都只被一个Acceptor的接受,并没有被超过半数以上的Acceptor接受。

最开始将【提案 = value】已经无法满足现在的需求,因为当一个Proposer发送多个提案到一个Acceptor的时候,需要使用一个编号来区分被提出的顺序。现在【提案=提案编号+value】。

虽然允许多个提案被选定,但必须保证所有被选定的提案都具有相同的value值。否则又会出现不一致。

P2:如果某个value为v的提案被选定了,那么每个编号更高的被选定提案的value必须也是v。

一个提案只有被Acceptor接受才可能被选定,因此我们可以把P2约束改写成对Acceptor接受的提案的约束P2a。

P2a:如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v。

只要满足了P2a,就能满足P2。

但是,考虑如下的情况:以立法过程为背景,假设总的有5个人大代表(Acceptor)。

人民法院(Proposer2)提出[M1,V1]的提案,人大代表2-5号(半数以上)均接受了该提案,于是对于人大代表2-5号和人民法院来讲,它们都认为V1提案是被选定的。此时,人大代表1在办完其它事务之后也参与到其中(之前人大代表1没有收到过任何提案),此时最高人民检察院(另一个提案者Proposer1)向人大代表1发送了[M2,V2]的提案(V2≠V1且M2>M1),对于人大代表1来讲,这是它收到的第一个提案。根据P1(一个Acceptor必须接受它收到的第一个提案。),人大代表1必须接受该提案!同时人大代表1认为V2被选定。这就出现了两个问题:

  • 人大代表1认为V2被选定,人大代表2-5和人民法院认为V1被选定。出现了不一致。

  • V1被选定了,但是编号更高的被人大代表1接受的提案[M2,V2]的value为V2,且V2≠V1。这就跟P2a(如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v)矛盾了。

c5220e38da90a0bf4887833a95a4fb08.png

所以,我们要对P2a约束进行加强!

P2a是对Acceptor接受的提案约束,但其实提案是Proposer提出来的,所有我们可以对Proposer提出的提案进行约束。得到P2b:

P2b:如果某个value为v的提案被选定了,那么之后任何Proposer提出的编号更高的提案的value必须也是v。

那么,如何确保在某个value为v的提案被选定后,Proposer提出的编号更高的提案的value都是v呢?

只要满足P2c即可:

P2c:对于任意的N和V,如果提案[N, V]被提出,那么存在一个半数以上的Acceptor组成的集合S,满足以下两个条件中的任意一个:

  • S中每个Acceptor都没有接受过编号小于N的提案。

  • S中Acceptor接受过的最大编号的提案的value为V。

Proposer生成提案

为了满足P2b,这里有个比较重要的思想:Proposer生成提案之前,应该先去『学习』已经被选定或者可能被选定的value,然后以该value作为自己提出的提案的value。如果没有value被选定,Proposer才可以自己决定value的值。这样才能达成一致。这个学习的阶段是通过一个『Prepare请求』实现的。

于是我们得到了如下的提案生成算法:

  • Proposer选择一个新的提案编号N,然后向某个Acceptor集合(半数以上)发送请求,要求该集合中的每个Acceptor做出如下响应(response)。

    (a) 向Proposer承诺保证不再接受任何编号小于N的提案。

    (b) 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案。

    我们将该请求称为编号为N的Prepare请求。

  • 如果Proposer收到了半数以上的Acceptor的响应,那么它就可以生成编号为N,Value为V的提案[N,V]。这里的V是所有的响应中编号最大的提案的Value。如果所有的响应中都没有提案,那 么此时V就可以由Proposer自己选择(一般为当前提案)。

    生成提案后,Proposer将该提案发送给半数以上的Acceptor集合,并期望这些Acceptor能接受该提案。我们称该请求为Accept请求。(注意:此时接受Accept请求的Acceptor集合不一定是之前响应Prepare请求的Acceptor集合)

Acceptor接受提案

Acceptor可以忽略任何请求(包括Prepare请求和Accept请求)而不用担心破坏算法的安全性。因此,我们这里要讨论的是什么时候Acceptor可以响应一个请求。

我们对Acceptor接受提案给出如下约束:

P1a:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案。

如果Acceptor收到一个编号为N的Prepare请求,在此之前它已经响应过编号大于N的Prepare请求。根据P1a,该Acceptor不可能接受编号为N的提案。因此,该Acceptor可以忽略编号为N的Prepare请求。当然,也可以回复一个error,让Proposer尽早知道自己的提案不会被接受。

因此,一个Acceptor只需记住:1. 已接受的编号最大的提案 2. 已响应的请求的最大编号。

Paxos算法描述

经过上面的推导,我们总结下Paxos算法的流程。

Paxos算法分为两个阶段。具体如下:

1.阶段一:

  • Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。

  • 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话) 作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。

2.阶段二:

  • 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor(和之前的Acceptor不一定相同)。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。

  • 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。

cf4b61c5ef272fcd87af2b5e8ef0788e.png

Learner学习被选定的value

Learner学习(获取)被选定的value有如下三种方案:

方案一

Acceptor接受到一个提案,就将该提案发送给所有Learners.

  • 优点:Learner能够快速获取被选定的value

  • 缺点:通信次数为M*N(M为提案数,N为Learner数)

方案二

Acceptor接受一个提案,就将提案发送给主Learner,主Learner再通知其它Learner

  • 优点:通信次数减少(M+N-1)(M为提案数,N为Learner数,M个提案发送给主Learner,然后主Learner通知N-1个Learner)

  • 缺点:单点故障问题(主Learner可能出现故障)

方案三

Acceptor接受一个提案,就将提案发送给Learner团,Learner团再通知其它Learner

  • 优点:解决了方案二单点故障问题,可靠性好

  • 缺点:实现复杂,网络通信复杂度高

如何保证Paxos算法的活性

通过选取主Proposer,就可以保证Paxos算法的活性。通过选取主Proposer,并规定只有主Proposer才能提出议案。这样一来只要主Proposer和过半的Acceptor能够正常进行网络通信,那么但凡主Proposer提出一个编号更高的提案,该提案终将会被批准,这样通过选择一个主Proposer,整套Paxos算法就能够保持活性。至此,我们得到一个既能保证安全性,又能保证活性的分布式一致性算法——Paxos算法。

3b96d376ae7823535ae052502ceab862.png

总结

到此,我们针对Paxos算法是什么、它的特性以及算法的具体推导过程做了详细的阐述。Paxos算法是现在很多一致性算法的变体,非常值得我们学习~

d3868be2b8ad65515c1220d9dce73cbe.gif

e1dd49c340929b3f73a2bbd583b3f6ef.png

往期推荐

如何跨 Namespace 同步 Secret 和 ConfigMap?

掘地三尺搞定 Redis 与 MySQL 数据一致性问题

Redis 内存满了怎么办?这样置才正确!

云原生的本手、妙手和俗手

1107585fcf3d87f5b311dd496012e919.gif

点分享

40a4e653d46145babbba1a419a75ad3d.gif

点收藏

686b1351579f42ab1a20f94a7ab95b28.gif

点点赞

2478452c997f525e49ceb781449fd280.gif

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java jdk myeclipse_java初体验(JDK+myeclipse)

前一段时间突击了C语言,主要是针对文件的操作,学习C的目的就是利用C处理oracle数据文件,在脱离oracle软件的情况下,提取出特定表的数据。行链接和行迁移再加上cluster表搞的头大,暂且一放,学习下java,了解下…

专访阿里云王伟民:一站式全链路,阿里云向云原生数据库2.0跃迁

简介:阿里云连续第二年进入Gartner《全球云数据库魔力象限》领导者象限,意味着国产数据库正在迅速崛起。 数据库与操作系统、中间件并称为基础软件,“核高基”中的“基”指的就是这三类基础软件产品,它们在软件产业中有举足轻重的…

媒体声音 | 云数据库,谁才是领导者?

简介:你们从2021年Gartner云数据库管理系统魔力象限中看到了什么…… 2021年新冠疫情进入第二年,对全球的社会、经济而言是不平凡之年,这句话也可用于概括云数据库的发展。随着中国厂商逐步进入全球云数据库市场重要舞台,我们也看…

再聊数据中心网络

作者 | 鲜枣课堂来源 | 小枣君本着“将通信科普到底”的原则,今天,我再继续聊一下这个话题。故事还是要从头开始说起。1973年夏天,两名年轻的科学家(温顿瑟夫和罗伯特卡恩)开始致⼒于在新⽣的计算机⽹络中,…

面向中后台复杂场景的低代码实践思路

简介:现实中,业务场景多,迭代频繁,变化快到跟不上,规则可能由多人掌握,无法通过一个人了解全貌; 还有业务所在行业固有的复杂度和历史包袱,这些问题都会让我们感到痛苦。 除了逻辑问…

阿里云发布云数据中心专用处理器CIPU, 构建新一代云计算架构体系

6月13日,阿里云智能总裁张建锋在峰会上正式发布CIPU(Cloud infrastructure Processing Units),这是为新型云数据中心设计的专用处理器,未来将替代CPU成为云计算的管控和加速中心。 在这个全新体系架构下,C…

Java依赖冲突高效解决之道

简介:由于阿里妈妈联盟团队负责业务的特殊性,系统有庞大的对外依赖,依赖集团六七十个团队服务及N多工具组件,通过此文和大家分享一下我们积累的一些复杂依赖有效治理的经验,除了简单技术技巧的总结外,也会探…

多分支集成发布各种坑怎么填?

简介:一文为你详细介绍云效分支模式的原理及实践,云效 Flow 这套灵活高效的分支模式可以让用户只关心集成和发布哪些特性分支,而对发布分支创建和管理、分支间合并等一系列工作,托付给云效完成。 小明的研发团队要发布一个版本&a…

Gartner:中国企业构建边缘计算解决方案最佳实践

作者 | Gartner研究总监 李晶 供稿 | Gartner 随着中国企业数字化成熟度和渗透度的不断提升,基础设施和运营 (I&O) 团队和领导者所需要提供的数字基础设施的位置也在逐渐增加,从云端、数据中⼼,延伸到了⽹络边缘,并且每个位置…

php生成pdf文档,PHP生成PDF文件类库大全[开源]

虽然 PHP 有附 PDFlib ,不过使用起来实在有点复杂。(PHP 说明文件中的范例)FPDF虽然现在已经停止更新了,但 FPDF 可谓是元老级的 PDF 链接库,短短的几行程序就可以产生出 PDF 档案。最可怕的是现今的PHP PDF 链接库大多是由 FPDF 衍生出来的。…

从阿里核心场景看实时数仓的发展趋势

简介:随着2021年双11的完美落幕,实时数仓技术在阿里双11场景也经历了多年的实践和发展。从早期的基于不同作业的烟囱式开发,到基于领域分层建模的数仓引入,再到分析服务一体化的新型融合式一站式架构,开发效率逐步提升…

QUIC技术创新 让视频和图片分发再提速

简介:在1月12日的「阿里云CDN产品发布会-新一代传输协议QUIC让CDN更快一步」之上,阿里云技术专家淮叶分享了QUIC技术及其应用落地实践,内容包含:QUIC协议介绍、相比TCP有哪些优势、应用场景以及技术落地实践中的协议库选择&#x…

Spring Boot Serverless 实战 | Serverless 应用的监控与调试

简介:Spring Boot 是基于 Java Spring 框架的套件,它预装了 Spring 的一系列组件,让开发者只需要很少的配置就可以创建独立运行的应用程序。在云原生的环境中,有大量的平台可以运行 Spring Boot 应用,例如虚拟机、容器…

一文读懂 Serverless 的起源、发展和落地实践

简介:Serverless 适合哪些业务场景?它可以对业务产生何种价值呢? 讲师 | 洛浩(阿里云云原生高级架构师) Serverless 的发展轨迹 2012 年,Serverless 这个单词第一次出现,由 Iron 公司提出&…

Mendix:数字化转型下一个目标,提供准时制信息

作者 | Mendix公司首席低代码解决方案官Jethro Borsje 供稿 | Mendix 从孤立系统到支持决策的信息体系 二十世纪下半叶,丰田开发的“Toyota Production System”(TPS)曾帮助公司提高了效率并能快速生产出高质量的汽车,TPS的价值得…

实战经验 | 怎样才能提升代码质量?

简介:提升代码质量的三个有效方法:领域建模、设计原则、设计模式。 影响代码差的根因 差代码的体现 我们可以列举出非常多质量差的代码的表现现象,如名字不知所意、超大类、超大方法、重复代码、代码难懂、代码修改困难……其中最为影响代码…

zblog php 静态化,ASP版ZBLOG全站静态化

现在好像很多人已经转战PHP版的ZBLOG阵营了,不过对于我建的小博客来说,ASP版的更加简单便捷,完全够用了。ASP版程序自带的文章页面静态化功能加上YTBuild这个插件可以实现全站静态化(文章页面纯静态化,其他页面伪静态化)&#xff…

简单、有效、全面的Kubernetes监控方案

简介:近年来,Kubernetes作为众多公司云原生改造的首选容器化编排平台,越来越多的开发和运维工作都围绕Kubernetes展开,保证Kubernetes的稳定性和可用性是最基础的需求,而这其中最核心的就是如何有效地监控Kubernetes集…

如何优雅保护 Kubernetes 中的 Secrets

来源 | 进击云原生现如今开发的大多数应用程序,或多或少都会用到一些敏感信息,用于执行某些业务逻辑。比如使用用户名密码去连接数据库,或者使用秘钥连接第三方服务。在代码中直接使用这些密码或者秘钥是最直接的方式,但同时也带来…

智能巡检告警配置实践

简介:智能异常分析的检测结果通过 SLS 告警功能输出到用户配置的通知渠道。在智能巡检场景中,单个任务往往会巡检大量的实体对象,涉及到的对象规则很多,我们通过SLS新版告警可以实现较好的对于巡检事件的管理。 智能异常分析的检…