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

从分布式系统的CAP理论出发,关注分布式一致性,以及区块链的共识问题及解决。

区块链首先是一个大规模分布式系统,共识问题本质就是分布式系统的一致性问题,但是又有很大的不同。
工程开发中,认为系统中存在故障(fault),但不存在恶意(corrupt)节点,而区块链,特别是公开链是落地到物理世界中,涉及到人性和利益关系,不可避免的存在信任以及恶意攻击问题。

分布式一致性处理的是节点失效情况(即可能消息丢失或重复,但无错误消息)的共识达成(Consensus)问题,主要是Paxos算法及衍生的Raft算法。

一、分布式系统的挑战

关于分布式系统有一个经典的CAP理论,

CAP理论的核心思想是任何基于网络的数据共享系统最多只能满足数据一致性(Consistency)、可用性(Availability)和网络分区容忍(Partition Tolerance)三个特性中的两个。

  • Consistency 一致性
    一致性指“all nodes see the same data at the same time”,即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。等同于所有节点拥有数据的最新版本。
  • Availability 可用性

可用性指“Reads and writes always succeed”,即服务一直可用,而且是正常响应时间。
对于一个可用性的分布式系统,每一个非故障的节点必须对每一个请求作出响应。也就是,该系统使用的任何算法必须最终终止。当同时要求分区容忍性时,这是一个很强的定义:即使是严重的网络错误,每个请求必须终止。

  • Partition Tolerance 分区容忍性

Tolerance也可以翻译为容错,分区容忍性具体指“the system continues to operate despite arbitrary message loss or failure of part of the system”,即系统容忍网络出现分区,分区之间网络不可达的情况,分区容忍性和扩展性紧密相关,Partition Tolerance特指在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。分区容忍就提高了。然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。

如图,Client A可以发送指令到Server并且设置更新X的值,Client 1从Server读取该值,在单点情况下,即没有网络分区的情况下,或者通过简单的事务机制,可以保证Client 1读到的始终是最新的值,不存在一致性的问题。

如果在系统中增加一组节点,Write操作可能在Server 1上成功,在Server 1上失败,这时候对于Client 1和Client 2,就会读取到不一致的值,出现不一致。如果要保持x值的一致性,Write操作必须同时失败,降低系统的可用性。

可以看到,在分布式系统中,同时满足CAP定律中“一致性”、“可用性”和“分区容错性”三者是不可能的。

在通常的分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica),网络分区是既成的现实,于是只能在可用性和一致性两者间做出选择。CAP理论关注的是绝对情况下,在工程上,可用性和一致性并不是完全对立,我们关注的往往是如何在保持相对一致性的前提下,提高系统的可用性。

二、数据一致性模型

在互联网领域的绝大多数的场景,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

对于一致性,可以分为从服务端和客户端两个不同的视角,即内部一致性和外部一致性。
没有全局时钟,绝对的内部一致性是没有意义的,一般来说,我们讨论的一致性都是外部一致性。外部一致性主要指的是多并发访问时更新过的数据如何获取的问题。

强一致性:
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。

弱一致性:
系统并不保证续进程或者线程的访问都会返回最新的更新过的值。用户读到某一操作对系统特定数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。

最终一致性:
是弱一致性的一种特例。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。

最终一致性模型根据其提供的不同保证可以划分为更多的模型,包括因果一致性和读自写一致性等。

三、两阶段和三阶段提交

在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。
典型的比如关系型数据库,由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。
但是,相互独立的节点之间无法准确的知道其他节点中的事务执行情况,所以两台机器理论上无法达到一致的状态。

如果想让分布式部署的多台机器中的数据保持一致性,那么就要保证在所有节点的数据写操作,要不全部都执行,要么全部的都不执行。
但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果。所以节点并不知道本次事务到底应该commit还是 roolback。

所以实现分布式事务,需要让当前节点知道其他节点的任务执行状态。常规的解决办法就是引入一个“协调者”的组件来统一调度所有分布式节点的执行。著名的是二阶段提交协议(Two Phase Commitment Protocol)和三阶段提交协议(Three Phase Commitment Protocol)。

1.二阶段提交协议

Two Phase指的是Commit-request阶段Commit阶段。

  • 请求阶段
    在请求阶段,协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。
    在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。
  • 提交阶段
    在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。
    当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行响应的操作。

可以看出,两阶段提交协议存在明显的问题:

  • 同步阻塞
    执行过程中,所有参与节点都是事务独占状态,当参与者占有公共资源时,第三方节点访问公共资源被阻塞。
  • 单点问题
    一旦协调者发生故障,参与者会一直阻塞下去。
  • 数据不一致性
    在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行commit,其余的参与者没有收到通知一直处于阻塞状态,这段时间就产生了数据的不一致性。

2.三阶段提交协议

Three Phase分别为CanCommit、PreCommit、DoCommit。

三阶段提交针对两阶段提交做了改进:

  • 引入超时机制。在2PC中,只有协调者拥有超时机制,3PC同时在协调者和参与者中都引入超时机制。
  • 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

四、Paxos算法的提出

二阶段提交还是三阶段提交都无法很好的解决分布式的一致性问题,直到Paxos算法的提出,Paxos协议由Leslie Lamport最早在1990年提出,目前已经成为应用最广的分布式一致性算法。

Google Chubby的作者Mike Burrows说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。

1.节点角色

Paxos 协议中,有三类节点:

  • Proposer:提案者

Proposer 可以有多个,Proposer 提出议案(value)。所谓 value,在工程中可以是任何操作,例如“修改某个变量的值为某个值”、“设置当前 primary 为某个节点”等等。Paxos 协议中统一将这些操作抽象为 value。
不同的 Proposer 可以提出不同的甚至矛盾的 value,例如某个 Proposer 提议“将变量 X 设置为 1”,另一个 Proposer 提议“将变量 X 设置为 2”,但对同一轮 Paxos 过程,最多只有一个 value 被批准。

  • Acceptor:批准者

Acceptor 有 N 个,Proposer 提出的 value 必须获得超过半数(N/2+1)的
Acceptor 批准后才能通过。Acceptor 之间完全对等独立。

  • Learner:学习者

Learner 学习被批准的 value。所谓学习就是通过读取各个 Proposer 对 value 的选择结果,如果某个 value 被超过半数 Proposer 通过,则 Learner 学习到了这个 value。

这里类似 Quorum 议会机制,某个 value 需要获得 W=N/2 + 1 的 Acceptor 批准,Learner 需要至少读取 N/2+1 个 Accpetor,至多读取 N 个 Acceptor 的结果后,能学习到一个通过的 value。

2.约束条件

上述三类角色只是逻辑上的划分,实践中一个节点可以同时充当这三类角色。有些文章会添加一个Client角色,作为产生议题者,实际不参与选举过程。

Paxos中 proposer 和 acceptor 是算法的核心角色,paxos 描述的就是在一个由多个 proposer 和多个 acceptor 构成的系统中,如何让多个 acceptor 针对 proposer 提出的多种提案达成一致的过程,而 learner 只是“学习”最终被批准的提案。

Paxos协议流程还需要满足几个约束条件:

  • Acceptor必须接受它收到的第一个提案;
  • 如果一个提案的v值被大多数Acceptor接受过,那后续的所有被接受的提案中也必须包含v值(v值可以理解为提案的内容,提案由一个或多个v和提案编号组成);
  • 如果某一轮 Paxos 协议批准了某个 value,则以后各轮 Paxos 只能批准这个value;

每轮 Paxos 协议分为准备阶段和批准阶段,在这两个阶段 Proposer 和 Acceptor 有各自的处理流程。

Proposer与Acceptor之间的交互主要有4类消息通信,如下图:

这4类消息对应于paxos算法的两个阶段4个过程:

  • Phase 1
    a) proposer向网络内超过半数的acceptor发送prepare消息
    b) acceptor正常情况下回复promise消息
  • Phase 2
    a) 在有足够多acceptor回复promise消息时,proposer发送accept消息
    b) 正常情况下acceptor回复accepted消息

3.选举过程

  • Phase 1 准备阶段

Proposer 生成全局唯一且递增的ProposalID,向 Paxos 集群的所有机器发送 Prepare请求,这里不携带value,只携带N即ProposalID 。

Acceptor 收到 Prepare请求 后,判断:收到的ProposalID 是否比之前已响应的所有提案的N大:
如果是,则:
(1) 在本地持久化 N,可记为Max_N。
(2) 回复请求,并带上已Accept的提案中N最大的value(若此时还没有已Accept的提案,则返回value为空)。
(3) 做出承诺:不会Accept任何小于Max_N的提案。

如果否:不回复或者回复Error。

  • Phase 2 选举阶段

P2a:Proposer 发送 Accept
经过一段时间后,Proposer 收集到一些 Prepare 回复,有下列几种情况:
(1) 回复数量 > 一半的Acceptor数量,且所有的回复的value都为空,则Porposer发出accept请求,并带上自己指定的value。
(2) 回复数量 > 一半的Acceptor数量,且有的回复value不为空,则Porposer发出accept请求,并带上回复中ProposalID最大的value(作为自己的提案内容)。
(3) 回复数量 <= 一半的Acceptor数量,则尝试更新生成更大的ProposalID,再转P1a执行。

P2b:Acceptor 应答 Accept
Accpetor 收到 Accpet请求 后,判断:
(1) 收到的N >= Max_N (一般情况下是 等于),则回复提交成功,并持久化N和value。
(2) 收到的N < Max_N,则不回复或者回复提交失败。

P2c: Proposer 统计投票
经过一段时间后,Proposer 收集到一些 Accept 回复提交成功,有几种情况:
(1) 回复数量 > 一半的Acceptor数量,则表示提交value成功。此时,可以发一个广播给所有Proposer、Learner,通知它们已commit的value。
(2) 回复数量 <= 一半的Acceptor数量,则 尝试 更新生成更大的 ProposalID,再转P1a执行。
(3) 收到一条提交失败的回复,则尝试更新生成更大的 ProposalID,再转P1a执行。

4.相关讨论

Paxos算法的核心思想:
(1)引入了多个Acceptor,单个Acceptor就类似2PC中协调者的单点问题,避免故障
(2)Proposer用更大ProposalID来抢占临时的访问权,可以对比2PC协议,防止其中一个Proposer崩溃宕机产生阻塞问题
(3)保证一个N值,只有一个Proposer能进行到第二阶段运行,Proposer按照ProposalID递增的顺序依次运行
(3) 新ProposalID的proposer比如认同前面提交的Value值,递增的ProposalID的Value是一个继承关系

为什么在Paxos运行过程中,半数以内的Acceptor失效都能运行?
(1) 如果半数以内的Acceptor失效时 还没确定最终的value,此时,所有Proposer会竞争 提案的权限,最终会有一个提案会 成功提交。之后,会有半过数的Acceptor以这个value提交成功。
(2) 如果半数以内的Acceptor失效时 已确定最终的value,此时,所有Proposer提交前 必须以 最终的value 提交,此值也可以被获取,并不再修改。

如何产生唯一的编号呢?
在《Paxos made simple》中提到的是让所有的Proposer都从不相交的数据集合中进行选择,例如系统有5个Proposer,则可为每一个Proposer分配一个标识j(0~4),则每一个proposer每次提出决议的编号可以为5*i + j(i可以用来表示提出议案的次数)。

推荐larmport和paxos相关的三篇论文:
The Part-Time Parliament
Paxos made simple
Fast Paxos

2PC/3PC和Paxos协议是经典的分布式协议,理解了它们以后,学习其他分布式协议会简单很多。

参考:
CAP theorem
浅谈分布式系统的基本问题:可用性与一致性
分布式系统入门到实战
图解分布式一致性协议Paxos
Paxos协议学习小结

原文地址:https://www.cnblogs.com/binyue/p/8645565.html

时间: 2024-10-23 02:56:55

从分布式一致性到共识机制(一)Paxos算法的相关文章

从分布式一致性到共识机制(三)拜占庭问题

分布式一致性问题,区块链里体现就是共识问题.共识机制就是在一个群体中的个体通过某种方式达成一致性的一种机制,比如在一个团队.或者一个公司里的个体意见不一致时,就需要有一个领导,由领导来做决定,保证团队达成共识. 目前的共识算法,主要有基于算力的POW,基于股权的POS和基于投票的DPOS算法,以及著名的拜占庭容错算法. 一.共识机制 团队里的共识机制延伸到普通的分布式系统里面,就是系统需要有一个master,系统的所有决定都由master来达成共识,在分布式系统里面master的选举其实就是基于

对标Eureka的AP一致性,Nacos如何实现Raft算法

一.快速了解Raft算法 Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它. 为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导选取(leader selection).日志复制(log replication).安全(safety),并且使用了更强的一致性来减少了必须需要考虑的状态. 相比Paxos,Raft算法理解起来更加直观. Raft算法将Server划分为3种状态,或者也可以称作角色: Leader 负责Client交互和l

【转载】Paxos以及分布式一致性的学习

开始搜出来这篇文章(link),发现不知所云,先忽略. 然后搜出来这篇文章(link),说是偏向工程实现,建议先看维基(link),但是维基打不开. 所以还是先看知乎的这篇文章吧(https://www.zhihu.com/question/19787937/answer/82340987) Lamport用两段话就描述清楚了它的流程,他老人家也说paxos其实是个简单的算法.但是是我在工程领域见过最为精妙的算法. 分布式一致性是个有趣的领域,而Paxos和类似的协议对这个问题的重要性不喻,在过

分布式 一致性Paxos算法(转载)

文章1比较通俗易懂,可以入门,转载地址是http://www.cnblogs.com/linbingdong/p/6253479.html Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难. 网上有很多讲解Paxos算法的文章,但是质量参差不齐.看了很多关于Paxos的资料后发现,学习Paxos最好的资料是论文<Paxos Made Simple>,其次是中.英文版维基百科对Paxos的介绍.本文试图带大家一步步揭开Paxos

&lt;从PAXOS到ZOOKEEPER分布式一致性原理与实践&gt;读书笔记-两阶段提交与三阶段提交

一.背景 本书第一章的分布式架构,写了从单机的acid到分布式的CAP.参见之前的文章.本篇是第二章的一致性协议部分,分两篇整理. 在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上.为了对用户提供正确的增\删\改\查等语义,我们需要保证这些放置在不同物理机器上的副本是一致的. 为了解决这种分布式一致性问题,有很多经典算法:如二阶段提交.三阶段提交,paxos算法. 二.二阶段提交(2PC) 二阶段提交(Two-phaseC

[从Paxos到ZooKeeper][分布式一致性原理与实践]&lt;一&gt;

目录 分布式架构 从集中式到分布式 从ACID到CAP/BASE 一致性协议 2PC与3PC Paxos算法 Paxos的工程实践 Chubby Hypertable Zookeeper与Paxos 初始Zookeeper Zookeeper的ZAB协议 使用Zookeeper 部署与运行 客户端脚本 Java客户端API 开源客户端 Zookeeper的典型应用场景 Zookeeper技术内幕 系统模型 序列化与协议 科幻端 会话 服务器启动 leader选举 ... Zookeeper运维

【转】Paxos算法细节详解

最近研究zookeeper因此就学习了一下paxos算法,一直没太看懂,今天找到了这篇文章描述的很清晰,转自:http://www.cnblogs.com/endsock/p/3480093.html Paxos分析 最近研究paxos算法,看了许多相关的文章,概念还是很模糊,觉得还是没有掌握paxos算法的精髓,所以花了3天时间分析了libpaxos3的所有代码,此代码可以从https://bitbucket.org/sciascid/libpaxos 下载.对paxos算法有初步了解之后,再

Paxos算法细节详解(一)--通过现实世界描述算法

最近研究paxos算法,看了许多相关的文章,概念还是很模糊,觉得还是没有掌握paxos算法的精髓,所以花了3天时间分析了libpaxos3的所有代码,此代码可以从https://bitbucket.org/sciascid/libpaxos 下载.对paxos算法有初步了解之后,再看此文的效果会更好:如果你也想分析libpaxos3的话,此文应该会对你有不小帮助:关于paxos的历史这里不多做介绍,关于描述paxos算法写的最好的一篇文章应该就是维基百科了,地址戳这里:http://zh.wik

Paxos算法简单介绍

一种基于消息传递且具有高度容错特性的一致性算法.解决在存在宕机或者网络异常的集群中对某个数据的值达成一致性,并且保证无论在发生以上任何异常都不会破坏整个系统的一致性,具有容错性. Paxos算法实现的是分布式系统多个结点之上数据的一致性,这个算法有如下特性 1.基于消息传递,允许消息传输的丢失,重复,乱序,但是不允许消息被攥改 2.在结点数少于半数失效的情况下仍然能正常的工作,结点失效可以在任何时候发生而不影响算法正常执行. 1.paxos算法综述 在paxos算法中,分为三种角色:propos