精华内容
下载资源
问答
  • 分布式一致性协议

    千次阅读 2019-01-26 19:52:04
    关于分布式系统的一致性模型有以下几种: 强一致性 当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值,直到这个数据被其他数据更新为止。 但是这种实现对性能影响较大,因为这意味着...

    一致性模型

    一致性(Consistency)是指多副本(Replications)问题中的数据一致性。关于分布式系统的一致性模型有以下几种:

    强一致性

    当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值,直到这个数据被其他数据更新为止。
    但是这种实现对性能影响较大,因为这意味着,只要上次的操作没有处理完,就不能让用户读取数据。

    弱一致性

    系统并不保证进程或者线程的访问都会返回最新更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。甚至不能保证可以访问到。

    最终一致性

    最终一致性也是弱一致性的一种,它无法保证数据更新后,所有后续的访问都能看到最新数值,而是需要一个时间,在这个时间之后可以保证这一点(就是在一段时间后,节点间的数据会最终达到一致状态),而在这个时间内,数据也许是不一致的,这个系统无法保证强一致性的时间片段被称为「不一致窗口」。不一致窗口的时间长短取决于很多因素,比如备份数据的个数、网络传输延迟速度、系统负载等。
    最终一致性在实际应用中又有多种变种:

    类型说明
    因果一致性如果 A 进程在更新之后向 B 进程通知更新的完成,那么 B 的访问操作将会返回更新的值。而没有因果关系的 C 进程将会遵循最终一致性的规则(C 在不一致窗口内还是看到是旧值)。
    读你所写一致性因果一致性的特定形式。一个进程进行数据更新后,会给自己发送一条通知,该进程后续的操作都会以最新值作为基础,而其他的进程还是只能在不一致窗口之后才能看到最新值。
    会话一致性读你所写一致性的特定形式。进程在访问存储系统同一个会话内,系统保证该进程可以读取到最新之,但如果会话终止,重新连接后,如果此时还在不一致窗口内,还是可嫩读取到旧值。
    单调读一致性如果一个进程已经读取到一个特定值,那么该进程不会读取到该值以前的任何值。
    单调写一致性系统保证对同一个进程的写操作串行化。
    一致性模型
    一致性模型

     

    一致性协议

    为了解决分布式系统的一致性问题,在长期的研究探索过程中,业内涌现出了一大批经典的一致性协议和算法,其中比较著名的有二阶段提交协议(2PC),三阶段提交协议(3PC)和 Paxos 算法。

    Google 2009年 在Transaction Across DataCenter 的分享中,对一致性协议在业内的实践做了一简单的总结,如下图所示,这是 CAP 理论在工业界应用的实践经验。

    CAP 理论在工业界的实践

    其中,第一行表头代表了分布式系统中通用的一致性方案,包括冷备、Master/Slave、Master/Master、两阶段提交以及基于 Paxos 算法的解决方案,第一列表头代表了分布式系统大家所关心的各项指标,包括一致性、事务支持程度、数据延迟、系统吞吐量、数据丢失可能性、故障自动恢复方式。

     

    分布式事务

    分布式事务是指会涉及到操作多个数据库的事务。其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务的决定必须产生统一的结果(全部提交或全部回滚)

    在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。但是,相互独立的节点之间无法准确的知道其他节点中的事务执行情况。所以从理论上讲,两台机器理论上无法达到一致的状态。如果想让分布式部署的多台机器中的数据保持一致性,那么就要保证在所有节点的数据写操作,要不全部都执行,要么全部的都不执行。但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果。所以他也就不知道本次事务到底应该commit还是 roolback。所以,常规的解决办法就是引入一个“协调者”的组件来统一调度所有分布式节点的执行。

    XA规范

    X/Open 组织(即现在的 Open Group )定义了分布式事务处理模型。 X/Open DTP 模型( 1994 )包括应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。一般,常见的事务管理器( TM )是交易中间件,常见的资源管理器( RM )是数据库,常见的通信资源管理器( CRM )是消息中间件。   

    通常把一个数据库内部的事务处理,如对多个表的操作,作为本地事务看待。数据库的事务处理对象是本地事务,而分布式事务处理的对象是全局事务。   所谓全局事务,是指分布式事务处理环境中,多个数据库可能需要共同完成一个工作,这个工作即是一个全局事务,例如,一个事务中可能更新几个不同的数据库。对数据库的操作发生在系统的各处但必须全部被提交或回滚。此时一个数据库对自己内部所做操作的提交不仅依赖本身操作是否成功,还要依赖与全局事务相关的其它数据库的操作是否成功,如果任一数据库的任一操作失败,则参与此事务的所有数据库所做的所有操作都必须回滚。    

    一般情况下,某一数据库无法知道其它数据库在做什么,因此,在一个 DTP 环境中,交易中间件是必需的,由它通知和协调相关数据库的提交或回滚。而一个数据库只将其自己所做的操作(可恢复)影射到全局事务中。

    XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商提供。

    二阶提交协议和三阶提交协议就是根据这一思想衍生出来的。可以说二阶段提交其实就是实现XA分布式事务的关键(确切地说:两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做)

     

    2PC

    它可以保证在分布式事务中,要么所有参与进程都提交事务,要么都取消事务,即实现 ACID 的原子性(A)。

    在数据一致性中,它的含义是:要么所有副本(备份数据)同时修改某个数值,要么都不更改,以此来保证数据的强一致性。

    2PC 过程

    2PC分为2个阶段:

    • 表决阶段

    1、事务询问

    Coordinator (协调者)向所有的参与者发送一个 vote request

    2、执行事务

    各个参与者节点执行事务操作,并讲Undo和Redo信息记入事务日志中

    3、各参与者向协调者反馈事务询问的响应.

    如果参与者成功执行了事务操作,那么就反馈给协调者vote_commit响应,表示事务可以执行,如果没有参与者成功执行事务,那么就反馈给协调者vote_abort响应,表示事务不可以执行.

    • 提交阶段

    Coordinator 收到所有参与者的表决信息,如果所有参与者一致认为可以提交事务,那么 Coordinator 就会发送 GLOBAL_COMMIT 消息,否则发送 GLOBAL_ABORT 消息;对于参与者而言,如果收到 GLOBAL_COMMIT 消息,就会提交本地事务,否则就会取消本地事务。

       

    2PC一致性问题

    2PC 在执行过程中可能发生 Coordinator 或者参与者突然宕机的情况,在不同时期宕机可能有不同的现象。

    情况分析及解决方案
    Coordinator 挂了,参与者没挂这种情况其实比较好解决,只要找一个 Coordinator 的替代者。当他成为新的 Coordinator 的时候,询问所有参与者的最后那条事务的执行情况,他就可以知道是应该做什么样的操作了。所以,这种情况不会导致数据不一致。
    参与者挂了(无法恢复),Coordinator 没挂如果挂了之后没有恢复,那么是不会导致数据一致性问题。
    参与者挂了(后来恢复),Coordinator 没挂恢复后参与者如果发现有未执行完的事务操作,直接取消,然后再询问 Coordinator 目前我应该怎么做,协调者就会比对自己的事务执行记录和该参与者的事务执行记录,告诉他应该怎么做来保持数据的一致性。

    还有一种情况是:参与者挂了,Coordinator 也挂了,需要再细分为几种类型来讨论:

    情况分析及解决方案
    Coordinator 和参与者在第一阶段挂了由于这时还没有执行 commit 操作,新选出来的 Coordinator 可以询问各个参与者的情况,再决定是进行 commit 还是 roolback。因为还没有 commit,所以不会导致数据一致性问题。
    Coordinator 和参与者在第二阶段挂了,但是挂的这个参与者在挂之前还没有做相关操作这种情况下,当新的 Coordinator 被选出来之后,他同样是询问所有参与者的情况。只要有机器执行了 abort(roolback)操作或者第一阶段返回的信息是 No 的话,那就直接执行 roolback 操作。如果没有人执行 abort 操作,但是有机器执行了 commit 操作,那么就直接执行 commit 操作。这样,当挂掉的参与者恢复之后,只要按照 Coordinator 的指示进行事务的 commit 还是 roolback 操作就可以了。因为挂掉的机器并没有做 commit 或者 roolback 操作,而没有挂掉的机器们和新的 Coordinator 又执行了同样的操作,那么这种情况不会导致数据不一致现象。
    Coordinator 和参与者在第二阶段挂了,挂的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。这种情况下,新的 Coordinator 被选出来之后,如果他想负起 Coordinator 的责任的话他就只能按照之前那种情况来执行 commit 或者 roolback 操作。这样新的 Coordinator 和所有没挂掉的参与者就保持了数据的一致性,我们假定他们执行了 commit。但是,这个时候,那个挂掉的参与者恢复了怎么办,因为他已经执行完了之前的事务,如果他执行的是 commit 那还好,和其他的机器保持一致了,万一他执行的是 roolback 操作呢?这不就导致数据的不一致性了么?虽然这个时候可以再通过手段让他和 Coordinator 通信,再想办法把数据搞成一致的,但是,这段时间内他的数据状态已经是不一致的了!

    2PC优缺点

    简单总结一下 2PC 的优缺点:

    • 优点:原理简洁清晰、实现方便;
    • 缺点:同步阻塞、单点问题、某些情况可能导致数据不一致。

    关于这几个缺点,在实际应用中,都是对2PC 做了相应的改造:

    1. 同步阻塞:2PC 有几个过程(比如 Coordinator 等待所有参与者表决的过程中)都是同步阻塞的,所有参与该事务操作的逻辑都处于阻塞状态,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。在实际的应用中,这个问题是通过超时判断机制来解决的,但并不能完全解决同步阻塞问题;
    2. Coordinator 单点问题:实际生产应用中,Coordinator 都会有相应的备选节点;
    3. 数据不一致:这个在前面已经讲述过了,如果在第二阶段,Coordinator 和参与者都出现挂掉的情况下,是有可能导致数据不一致的。

     

    3PC

    三阶段提交协议(Three-Phase Commit, 3PC)最关键要解决的就是 Coordinator 和参与者同时挂掉导致数据不一致的问题,所以 3PC 把在 2PC 中又添加一个阶段,这样三阶段提交就有:CanCommit、PreCommit 和 DoCommit 三个阶段。

    3PC 过程

    • CanCommit

        1.事务询问协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
        2.响应反馈参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No

    • PreCommit

    执行事务预提交:如果 Coordinator 接收到各参与者反馈都是Yes,那么执行事务预提交:

    1. 发送预提交请求:Coordinator 向各参与者发送 preCommit 请求,并进入 prepared 阶段;
    2. 事务预提交:参与者接收到 preCommit 请求后,会执行事务操作,并将 Undo 和 Redo 信息记录到事务日记中;
    3. 各参与者向 Coordinator 反馈事务执行的响应:如果各参与者都成功执行了事务操作,那么反馈给协调者 ACK 响应,同时等待最终指令,提交 commit 或者终止 abort,结束流程;

    中断事务:如果任何一个参与者向 Coordinator 反馈了 No 响应,或者在等待超时后,Coordinator 无法接收到所有参与者的反馈,那么就会中断事务。

    1. 发送中断请求:Coordinator 向所有参与者发送 abort 请求;
    2. 中断事务:无论是收到来自 Coordinator 的 abort 请求,还是等待超时,参与者都中断事务
    • doCommit

    执行提交

    1. 发送提交请求:假设 Coordinator 正常工作,接收到了所有参与者的 ack 响应,那么它将从预提交阶段进入提交状态,并向所有参与者发送 doCommit 请求;
    2. 事务提交:参与者收到 doCommit 请求后,正式提交事务,并在完成事务提交后释放占用的资源;
    3. 反馈事务提交结果:参与者完成事务提交后,向 Coordinator 发送 ACK 信息;
    4. 完成事务:Coordinator 接收到所有参与者 ack 信息,完成事务。

    在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。(其实这个应该是基于概率来决定的,当进入第三阶段时,说明参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。 )

    中断事务:假设 Coordinator 正常工作,并且有任一参与者反馈 No,或者在等待超时后无法接收所有参与者的反馈,都会中断事务

    1. 发送中断请求:Coordinator 向所有参与者节点发送 abort 请求;
    2. 事务回滚:参与者接收到 abort 请求后,利用 undo 日志执行事务回滚,并在完成事务回滚后释放占用的资源;
    3. 反馈事务回滚结果:参与者在完成事务回滚之后,向 Coordinator 发送 ack 信息;
    4. 中断事务:Coordinator 接收到所有参与者反馈的 ack 信息后,中断事务。

    3PC 分析

    3PC 虽然解决了 Coordinator 与参与者都异常情况下导致数据不一致的问题,3PC 依然带来其他问题:比如,网络分区问题,在 preCommit 消息发送后突然两个机房断开,这时候 Coordinator 所在机房会 abort, 另外剩余参与者的机房则会 commit。

    而且由于3PC 的设计过于复杂,在解决2PC 问题的同时也引入了新的问题,所以在实际上应用不是很广泛。

    2PC与3PC的区别

    相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

     

    展开全文
  • 解决的问题2.1 从流量说起2.2 从一主多从到分布式一致性协议2.2.1 一主多从2.2.2 分布式一致性协议2.2.3 总结2.3 分布式事务2.3.1 概念2.3.2 思考3. 具体实现协议3.1 分布式一致性协议3.1.1 多主协议3.1.2 单主协议...

    1. 写在最前面

    从隔壁大佬那边借来了 zookeeper 的协议 zap 的论文介绍,原本想对比一下 zap 和 raft 协议的异同。但是脑海里突然想到一句话「授人以鱼,不如授之以渔」。很多时候知识本身并不能产生多大价值,真正产生价值是要理解该知识使用的场景。

    注:本文并不会过多介绍分布式事务和一致性性协议的细节,仅从使用场景的角度进行分析。

    2. 解决的问题

    2.1 从流量说起

    🤔 思考一个业务场景,假设服务 300 qps 请求,是不是压根就不需要考虑分布式事务、一致性协议之类的问题,请求完全可以靠单机就能够抗住。

    那么随着业务的扩展流量增加到 3kqs 或者 300k qps 应该玩耍呢?

    在这里插入图片描述

    总结:

    • 单机:业务量很小,代码均放在一个项目中,项目部署的时候使用一台服务器

    • 集群:单机处理达到瓶颈的时候,单机复制几份,构成一个「集群」

      注:集群附加引入了负载均衡(LB)的概念

    • 分布式:将一个完整的系统,按照业务功能,拆分成一个个独立子系统,子系统之间通过 RPC 调用进行通信。例子🌰:将一个电商服务,拆分成用户服务、产品服务、订单服务、后台管理服务、数据分析服务等。

      拆分子系统的优点:

      • 解耦,各个子系统可以独立开发、测试、部署(ps 多人开发一份系统,解冲突想不想要原地爆炸💥
      • 细粒度优化系统的瓶颈,比如订单服务到瓶颈的时候仅仅扩容订单服务的集群即可
      • 复用性,比如将用户系统作为单独的服务,为该公司的所有产品提供服务,减少重复代码的开发

    2.2 从一主多从到分布式一致性协议

    古人教育我们「鸡蛋不要放在一个篮子里」,同理为了服务的稳定性,在真实的生产环境下,对企业而言重中之重的用户和服务数据常常是备份在多个服务节点上。

    注:事情不可能只有一面,多备份为容灾带来了好处,但同时也会服务的可用性和性能带来了影响。

    2.2.1 一主多从

    假设在一主多从数据备份的场景下,对于服务而言:

    • 性能:整体性能的瓶颈会受到处理最慢的节点影响。比如:server1/server3/server4 已经完成了同步,但是因为处理速度较慢的 server2 并未完成,所以对于 server 整个操作也就没有完成
    • 可用性:一旦 server2 处于不可用的情况下,整个 server 即不可用,增加了不可用的风险

    在这里插入图片描述

    2.2.2 分布式一致性协议

    提问:分布式一致性协议真的有传闻中的那么优秀嘛?

    注:分布式一致性协议是为了维护各个节点数据的一致性,换句话说,就是使集群中节点存储的数据一模一样。

    根据大部分分布式一致性协议设计的思路,假设集群中有 n 个节点,Leader 节点,只要收到 n/2+1 Follow 节点回复操作提交,该操作即可视为提交,且已提交的操作不会丢失,即使发生新一轮的选举。(ps:不了解该协议的小朋友阔以自己狠戳参考资料学习,笔者只能帮你到这里了

    分布式一致性协议的复制如下图所示,由分析可知,即使 server2 处理速度慢或者 server2 不可用,整个 server 集群还是可用的。可见分布式一致性协议从性能和使用性的角度上分析,完胜。

    注:分布式一致性协议不是银弹,它也有缺点,比如持续的 leader 选举,这依然会导致服务不可用,不过概率和时间上来说会更小🤔

    在这里插入图片描述

    2.2.3 总结

    • 一主多从和分布式一致性协议均可以用于维护各个节点数据的一致性
    • 分布式一致性协议较一主多从的模式有高的稳定性且处理速度不受最慢的节点影响

    2.3 分布式事务

    假设一个电商平台的下单服务操作,需要调用以下的子系统完成整个下单的流程。因为依赖较多的子系统,引入了更多的不稳定因素。所以为了保证用户下单行为的正确,此处需要引入分布式事务。解决用户在下单流程中失败的问题。

    在这里插入图片描述

    2.3.1 概念

    分布式事务的概念很简单,要么所有操作都执行,要么所有操作都不执行,不允许出现执行一半的场景。比如:

    • 订单服务和库存服务调用成功
    • 积分服务调用失败
    • 仓储服务并未执行

    2.3.2 思考

    几乎所有新技术的出现一定是为了解决某一类特定的问题,但是大多数时候,我们都只顾着去学习新技术,而忘记了去深入探究,它到底解决了什么问题。

    • 你知道 VM 和 continer 是啥,怎么用,但是思考过它们解决了什么问题吗?资源利用率嘛?
    • 你知道 serverless 的概念,但是它真正能产生的价值是什么?提效产研嘛?
    • 你知道 service mesh 的概念,甚至去看过了它的源码?但是你们公司真的需要它嘛?它能够解决贵公司面临的问题嘛?

    「not what but why」。有位大佬吐槽过我「不要手里拿一个锤子就看啥都像钉子,就算真的是个钉子,你用木头不能锤嘛?你用石头不能锤嘛?」🤔

    3. 具体实现协议

    以下内容仅做归纳,完全木有细节,可以自行跳跃式阅读。

    3.1 分布式一致性协议

    3.1.1 多主协议

    • Gossip 算法:由初始的几个节点向周围互相传播,到后期的大规模互相传播,最终达到一致。
      • 实际使用: redis 集群消息同步
    • Pow 算法:大量的节点参与竞争,通过自身的工作量大小来证明自身的能力,最终能力最大的节点优胜。
      • 实际使用:比特币引入了 Pow 算法

    3.1.2 单主协议:

    • Zap 算法: zookeeper 实现了该算法

    • Paxos 算法

    • Raft 算法

    此处还欠缺一些开源实现好的算法,但是本着自己动手丰衣足食的策略,我就不罗列了。

    3.2 分布式事务

    以下是实现分布式事务的几种方式:

    • 2PC 两阶段提交
    • 3PC 三阶段提交
    • TCC 补偿事务协议 (try/confirm/cancel)

    注:🤔我觉得 2PC 和 3PC 是由协调者控制是否要提交,而 TCC 补偿事务协议则由业务方控制是否要提交

    4. 碎碎念

    不是拖延症晚期的感觉还是挺好的,居然周一就写完了,撒花

    • 人生中没有哪件事情是无用的,即使不能得到夸奖,不能被人认可,至少我希望能竭尽全力,做好能做的每一件事。所以,我现在又要去做所谓无用功了。《校对女孩》

    有用也好,无用也罢,总之自己觉得开心就好啦。

    5. 参考资料

    展开全文
  • 在理解分析分布式一致性协议前,我们必须先看下CAP理论 CAP CAP是指在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)这三个要素最多只能同时实现两点,不...

     在理解分析分布式一致性协议前,我们必须先看下CAP理论

    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特指在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

    比如一个服务有3个节点,中国,美国,新加坡,如果数据只有一份,如果数据只在中国,那么美国用户访问数据流程是“美国节点->中国节点->中国数据“来实现的。这时如果美国和中国之间的网络断/高延时了,即出现分区,美国用户就没法访问到该数据。为了解决这个问题,目前都是每个节点都有一份数据备份,即中国,美国,新加坡都有一份数据,这样美国节点和中国节点哪怕临时中断,美国用户还是可以访问美国的数据。但是数据分处不同地区,需要同步,但同步有延时,数据可能不一致。要保障一致,那就必须等写操作在所有节点完成才读,这个时间又是不确定的,又会带来可用性问题,这就是C,A,P不可兼得即CAP理论。

    • 具体工程场景

      • 传统数据库都是假设不保证P的,因为传统数据库都是单机或者很小的本地集群,假设网络不存在问题,出现问题手工修复。所以,损失分区容错(P)只保证CA相当于就是一个单体应用,根本不是分布式,其实在分布式出现之前都是这么搭系统,但是倘若这种系统的节点之一挂了,整个系统就直接宕掉了,不符合目前现实需求(高扩展容错)。分布式是要求单个节点故障(概率太高了)系统仍能完成运行。搭建分布式就是间接要求必须保证P,即P是现实,那C和A就无法同时做到,需要在这两者之间做平衡。

      • 像银行系统,是通过损失可用性(A)来保障CP,银行系统是内网,很少出现分区不可达故障状态,一旦出现,不可达的节点对应的ATM就没法使用,即变为不可用。同时如果数据在各分区未达到一致,ATM也是Loading状态即不可用。

      • 在互联网实践中,可用性又是极其重要的,因此大部分是通过损失一致性(C)来保障AP,当然也非完全牺牲一致性,使用弱一致性,即一定时间后一致的弱一致性,当数据还在同步时(WRITE之后),使用上一次的数据。

        下面我们就来分析讨论今天的重点分布式一致性算法, 在理解Paxos之前我们必须先了解2PC和3PC。

     

    二阶段提交协议(2PC)

     

    协议详情

     

     

     

    改进

        相比一阶段协议,分两步可以让事务先执行然后再提交,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶段将是耗时极短,耗时极短意味着操作失败的可能性也就降低。

     

    缺陷

    • 同步阻塞问题

      执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。

    • 单点故障

      由于协调者的重要性,一旦协调者发生故障,参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的 参与者 还都处于锁定事务资源的状态中,而无法继续完成事务操。尽管协调者挂掉后可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题。

    • 数据不一致

      在P2A中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接受到commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交,于是整个分布式系统便出现了数据不一致性的现象。

    三阶段提交(3PC)

    协议详情

    改进

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

    • 在第一阶段和第二阶段中插入一个准备阶段,第一阶段canCommit并不执行事务,这样当第一阶段失败或者timeout时,不占用事务资源不需要回滚(提高效率减少事务阻塞)。

    • 引入超时机制。在2PC中,只有协调者拥有超时机制,3PC同时在协调者和参与者中都引入超时机制, 主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后主动提交释放资源,降低了阻塞时间。由于有第一阶段canCommit的yes才会进入第三阶段,因而该阶段极大概率是commit而不是rollback,因而当协调者挂掉后,默认执行commit是最接近正确的行为。

    缺陷

        和2CP一样,3CP还是可能会存在不一致性问题,比如,因而适合本地(无网络情况)或者网络非常好的情况。

    Paxos

        二阶段算法存在一个致命缺点,就是每个阶段协调者需要等到所有参与者的ack, 即只要有一个节点有故障,就会导致无效甚至整个系统出现问题, 这个概率还是很高。因而Paxos算法来了,Paxos有个很特别的就是协调者(proposer)只需等到超过1/2(多数派)的节点同意而不是全部节点,这样只有当1/2的节点同时出现故障整个系统才会有问题,加上同时这个限定条件后,这个系统的故障概率是极低极低的。由于只需超过1/2节点同意就执行操作,很明显不是所有节点都保持一致了,因而需要额外的逻辑来保障一致性,这个就是paxos的锁定,即一旦一个值被多数节点同意并提交,该值就被锁定了,剩下的少于1/2节点没法修改该值,并能从其他节点获取到这个设定的值,这个过程也叫learning过程,这个过程的proposer是learner角色。从这个角度我们可以看出参与者也可以是协调者,如果是数据同步过程,这个过程中参与者从协调者角色切换成了学习者。

    协议详情

    • 第一阶段A

    Proposer选择一个提议编号round_n,向所有的Acceptor广播Prepare(round_n)请求。

    • 第一阶段B

    Acceptor接收到Prepare(round_n)请求,若提议编号round_n比之前接收的Prepare请求都要大,则承诺将不会接收提议编号比round_n小的提议,并且带上之前Accept的提议中编号小于n的最大的提议,否则不予理会。

    • 第二阶段A

    Proposer得到了多数Acceptor的承诺后,如果没有发现有一个Acceptor接受过一个值,那么向所有的Acceptor发起自己的值和提议编号round_n,即(round_n, my_value),否则,从所有接受过的值中选择对应的提议编号最大的,作为提议的值,提议编号仍然为round_n,即(round_n, old_accepted_value)。

    • 第二阶段B

    Acceptor接收到提议后,如果该提议编号round_n不违反自己做过的承诺,则接受该提议并Ack Proposer。不违背承诺有两个部分。

    • round_n >= prepare/accepted的round

    • 如果已经有accepted value

    proxs的核心

    • 所有节点都是诚实的,即都按照规则行事

      一个提议只需被1/2半数以上节点同意(Promise),Proposer即可进行下一步。

    • 当一个提议被多数派接受(Accepted)后,这个提议对应的值被Chosen(选定),一旦有一个值被Chosen,那么只要按照协议的规则继续交互,后续被Chosen的值都是同一个值,也就是这个Chosen值被锁定,所有节点只能获取到这个值。

    • 所以一个值在Acceptor看来有3种状态:未赋值,Acceptor, Choosen状态

    如何确定编号

        上面提到的编号round是具体一个人的round, 它不是全局的,全局的就存在同步问题。因而proposer的真正编号是nodeid 【+】 round, 具体的方案有如下几种。

    实例推演分析

        接下来我们来具体分析各种case,假设总共有5个节点

    • 【1-P1A】 Node1发起proposer, prepare(1),  【1-P1B】然后收到2个Promised{1, {null, null}}, 加上自己总数3>5*1/2

    • 【1-P2A】因而Node1发起Accept{1, value},  这时又分两种情况

      • 【1-P2B】收到2个Node的Accepted{1, value}, 加上自己总数3>5*1/2, 这个value就被Chosen, 后续不管发起多少propose, 该值都会被不会被改变。其实目前只有Node1知道该值被Chosen了,如果客户端访问这个值,Node1是可以直接返回该值的。但是其他节点Node2~Node5并不知道该值有>1/2的节点Accepted, 因而并不认为该值被Chosen, 因而如果有client访问Node2节点该值,Node2是不能立即返回该值的,但Node2可通过发起一次Propose即prepare(2)【2-P1A】,    这时就有几种情况

        • 【2-P1B-1】从其他节点收到过Promised{2, {1, value}},  然后会接下来会发起【2-P2A】 Accept{2, value},如果收到超过1/2节点的 Accepted{2, value} 【2-P2B】,表明该值已经被Chosen是确定状态了,然后Node2就可以返回给客户端了,这个过程就是Learn过程(也称重确认)。这个过程发起的Accept动作会让更多节点Accepted(value),即让更多人知道该值,既是Learn也是传播。

        • 【2-P1B-2】从其他节点未收到过Promised{2, {1, value}} (【1-P2B】中所有Accepted的节点都offline/timeout才会出现这种case),  只收到Promised{2, {null, null}}, 由前面的协议可知,Promised{2, {null, null}}的数量不可能超过1/2s数量,因而这次Propose会失效,Node2会重新发起Propose(3), 重复前面的流程【2-P1A】,这时前面Accepted(1, value)中的任意节点online了,就会进入到【2-P1B-1】分支,然后Node2就Chosen了value, 直接返回给客户端,这个过程也说明一个值被Chosen后,其他节点可能会有短暂的异常非同步状态,但是最终还是会Chosen该值,是收敛的,专业词汇叫活性。

      • 【1-P2B-2】收到1个Node(假设Node5)的Accepted{1, value}, 加上自己总数2<5*1/2, 未超过多数,这时尽管该值未被Chosen,但是该值被部分节点Accepted, 在下次propose时被Chosen的概率也是很大的, 因为下次节点(假如Node2)发起新的propose, prepare(2) 【2-P1A】。

        • 【2-P1B-1】只要Node5在线,那么Node2就会收到Node5的Promised(2, {1, value}}, 进而接受Node5已经Accepted的值value, 然后继续发起Accept(2, value), 这一次value被Accepted的节点数就增大了,进而可能过半,进而被Chosen,这个过程充分体现了尽可能达成一致的规则,即尽可能使用上次多数人promised(表决)的结果, 然后尽力广播这个表决结果让更多的节点Accepted(执行),达到被chosen(确定)的结果。

        • 【2-P1B-2】Node5未在线,且Node2就会收到2个的Promised(2, {null, null}}, 超过多数,因而会发起Accept(2, value2),然后又有两种情况。

        • 收到超过半数的Accept(2, value2), 那么value2就被chosen确定了。

      • 未收到超过半数的Accept(2, value2), 那么说明系统被分为两个小组存在分歧了,一个组支持value, 一组支持value2。如果Node1和Node2交替重试propose,  这个冲突甚至可能会一直持续,这个就是paxos里的死锁现象,即当有多个proposer交错提交时,会导致大量节点不停的提交新的propose覆盖未被Chosen的老propose,进而持续导致没有任何一个propose达到chosen(确定)状态。这个很明显是因为Paxos允许任何参与者都可以是proposer并提出Propose。

    Paxos的落地

    Multi-Poxis, Raft, Zab(中心化分布式一致性协议)

        Paxos相对偏学术,是一种广义抽象,理解和落地相对复杂,同时Accept和Learn阶段存在不同程度的活锁情况, 总的来说主要有如下缺点

    1. 由于有多个 Proposer,可能会出现活锁

    2. Paxos只能确定一个值,无法用作数据的连续写同步

    3. 提案的最终结果可能只有部分 Acceptor 知晓,不是每个节点都同步到Log被chosen确定这一信息。

    因而工程落地上有不同的优化, 具体如下:

    • 活锁优化

            因而在工程落地上有了针对具体场景添加约束来尽量降低活锁概率的方案,比如Fast Paxos算法在此基础上作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer。选择Leader的方法有很多,采用前面标准的Paxos协议也能选出Leader。但是在实际工程中,针对Leader这个可以优化,比如标准的Paxos协议prepare阶段,优先级是按照round值的,由于在迭代的过程中round值会不停变化,会导致promise的返回值不停的变化,不利于收敛。如果我们把优先级规则从round变成节点序号node_id,那么规则就趋向于收敛固定的。比如节点id越小的,优先级越高,那么不论怎么迭代,promise都是优先同意node_id=0的提议,也就是说能更快的进入到Accept阶段。比如Multi-Paxos就是采用Basic-Paxios来选择Leader。当然考虑到Leader选举确定后(chosen后)需要最快速的同步到所有节点,且有更复杂的优先级规范,同时标准paxos协议偏复杂,其他工程实践中很少使用这种优化的标准paxos协议来选取Leader。Leader选举协议有如下Zookeeper的FastLeaderElecetion, Redis的哨兵模式哨兵leader选举和集群模式leader选举, 我将单独列一篇文章来详细描述这些Leader选举协议。

    • 多条数据记录同步优化

            从上面的Paxos的介绍可以看出,Paxos只能写入一条记录,一旦被Chosen就不能被修改,当时我们现实情况是经常要连续不断的写入新数据的,Paxos如何解决呢?这个比较好解决,Paxos的一次提交只做一件事我们称为一个paxos实例,比如写一条日志Log1(delete id=1)。如果要写多条日志比如Log2(delete id=2),那就需新建一个paxos实例,实例和实例之间是完全独立的,具体实现上,每个参与者可建立这样的一个三维数据(instance_id, round, value),  每个instance_id的交互按照poxis协议的规范处理处理round和value值。由于Basic-Paxos并不假设一段时间内只有唯一的proposer,因此可能由集群内的任意server发起redolog同步,因此不能由单一server维护instance_id,而是需要进行分布式协商,为不同的Log分配全局唯一且有序的instance_id(LogId)。同时Accept应答prepare消息和Accept消息前都要持久化本地Log,因而一次Log同步需要3次网络交互加2次写本地磁盘。并且在高并发的情况下,不同Log可能被分配到相同的LogId,这时最差可能会在accept阶段才会失败重试。

            Multi-Paxos:在Paxos集群中利用Basic-Paxos协议选举唯一的leader,在leader有效期内所有的议案都只能由leader发起,这里强化了协议的假设:即leader有效期内不会有其他server提出的议案。因此对于Log的同步过程,我们可以简化掉产生LogId阶段和prepare阶段,而是由唯一的leader产生logID,然后直接执行accept,得到多数派确认即表示Log同步成功。事实上,Multi-Paxos协议并不假设全局必须只能有唯一的leader来生成日志,它允许有多个“自认为是leader的server”来并发生成日志,这样的场景即退化为Basic-Paxos。

    • Learn优化(数据确认)

            如上一章节所知,读取一个已经chosen的value也是需要执行一轮Paxos过程的(即Learn过程,也叫重确认),在实际工程中做数据恢复时,对每条日志都执行一轮Paxos的代价过大,因此引入需要引入一种被成为confirm的机制,即Leader(Proposer)持久化一条日志,得到多数派的accept后,就再写一条针对这条日志的confirm日志,表示这条日志已经确认形成了多数派备份,在回放日志时,判断如果一条日志有对应的confirm日志,则可以直接读取本地内容,而不需要再执行一轮Paxos。confirm日志只要写本地即可,不需要同步到备机(Follower),但是出于提示备机及时回放收到日志的考虑(备机收到一条日志后(日志处于Accepted状态)并不能立即回放,需要确认这条日志已经形成多数派备份(Chosen状态)才能回放)。当然,Leader也会批量的给备机同步confirm日志。出于性能的考虑,confirm日志往往是延迟的成批写出去,因此仍然会出现部分日志已经形成多数派备份,但是没有对应的confirm日志的情况,对于这些日志,需要在恢复过程中进行重确认。

    • Leader模式"幽灵复现"问题

      Mutlti-Paxos下存在Leader切换情况,并且每个记录(Paxos实例)是完全独立的,因而是可能存在非顺序确认的,当然同一个Leader下日志是有顺序的,这个有点像多线程并发执行,同一个线程里的顺序是确定,线程之间的执行顺序谁知道呢?日志非顺序确认,就会出现客户端开始访问不到第7条记录,但是能访问到第20条记录,然后后面7确认后,客户端又能访问到第7条日志了。具体示例如下:

    • 第一轮中A被选为 Leader,写下了 1-10 号日志,其中 1-5 号日志形成了多数派,并且已给客户端应答,而对于 6-10 号日志,客户端超时未能得到应答。

    • 第二轮,A 宕机,B 被选为 Leader,由于 B 和 C 的最大的 LogID 都是 5,因此 B 不会去重确认 6 - 10 号日志,而是从 6 开始写新的日志,此时如果客户端来查询的话,是查询不到上一轮 6 - 10 号 日志内容的,此后第二轮又写入了 6 - 20 号日志,但是只有 6 号和 20 号日志在多数派。

    • 第三轮,A 又被选为 Leader,从多数派中可以得到最大 LogID 为 20,因此要将 7 - 20 号日志执行重确认,其中就包括了 A 上的 7-10 号日志,之后客户端再来查询的话,会发现上次查询不到的 7 - 10 号日志又像幽灵一样重新出现了。

         怎么解决“幽灵复现”问题?新任 Leader 在完成日志重确认,开始写入新的 Log 之前,先写出一条被称为 StartWorking 的日志,这条日志的内容中记录了当前 Leader 的 EpochID( 可以使用 Proposalid 的值),并且 Leader 每写一条日志都在日志内容中携带现任 Leader 的 EpochID。回放时,经过了一条 StartWorking 日志之后,再遇到 EpochID 比它小的日志,就直接忽略掉,比如按照上面例子画出的这张图,7 - 19 号日志要在回放时被忽略掉。

        Multi-Paxos就是使用上述几个优化的Paxos算法, ZAB和Raft都是衍生自Multi-Paxos,由于Multi-Paxos提出的Leader概念,ZAB和Raft就强化Leader视角,以Leader这个前提和现实需求来设计实现,本质上都是Paxos基础理论来保障一致性的。这三个协议的不同主要体现在下面几点

    • Leader选举方式不同

      • Mutil-Paxos采用Base-Paxos选举

      • Raft广播式互相计数方式

      • raft是选自己,节点发起投票,大家根据规则选择投与不投,看自己的票数是否成为Leader

    • raft集成了成员管理,这个比较精妙

    • Raft, zab能保障日志连续性

    • raft增加了committed状态,这个在paxos里没有具体说

    • raft给你的基本是伪代码的描述,方便实现

    PBFT(去中心分布式一致性协议)

        中心化一致性协议有一个重要的前提是参与者不作恶,因为参与者都是由一个实体管理,参与者都是不会违背协议的规范。而去中心化就不一样,参与者(节点机器)分散在各地,参与者是有可能故意不遵守规范的,比如Paxos中,如果Proposer在没有收到多数派的promise反馈仍发起Accept消息,就会导致该节点有无上权力,可以更新已经被Chosen的数据, 完全违背了规范。那是不是就不存在去中心化一致性协议呢?其实很简单,去中心化的情况下节点作恶会造成影响的原因是参与者没法验证Proposer是否在遵守规则,如果每个节点的回复都加上签名就能解决这个问题。比如每个参与者在回复promise时都通过自己的私钥对promise回复签名,那么一个Proposer如果没有收到多数派的promise"同意",Proposer就没法拿到多数派的"同意"签名,哪怕它违背规范发起Accept,其他的参与者也会因为它没有多数派的签名而不响应,也就是你可以作恶但是没用。

        那在去中心化的分布式系统中,如果Paxos要能容忍f个故障节点和f个作恶节点,多数派要为多少?故障节点收到通信后不会返回结果,作恶节点收到通信后会返回错误的结果。

        假设节点总数是n,其中故障节点有f,那么剩下的正确节点为n- f,意味着只要收到n - f个消息就能做出决定,但是这n - f个消息有可能有f个是由作恶节点冒充的,那么正确的消息就是n-f-f个,为了多数一致,正确消息必须占多数,也就是n - f - f > f 但是节点必须是整数个,所以n最少是3f+1个。所以在去中心化场景下,Paxos的多数派为n-1/3f +1, 即收到2/3*n+1个节点的消息即可做出决定,可见这个节点数比中心化时的1/2*n + 1要严格不少。接下来我们规范化中心化paxos和去中心化下poxis的流程来对比下这种的区别。

    • 标准Paxos交互图

     

        Basic-paxos, Proposer在接收到多数派的Accepted消息后知道该值已经被chosen(confirm不可变更), 此时proposer已经可以回复Client, 但是其他节点不知道该值已经被confirm, 仍然不能reply客户端,需要通过一次propose过来来确认值。

    • 带confirm的paxios交互图

            上面我们提到过,basic-poxis, 在proposer收到多数派的accepted后,也只有proposer知道该值被chosen(confirm),其他节点要确定这个值,需要通过一次propose过来来确认值, 因此raft等协议增加一个confirm交互来向其他节点广告该值已经被confirm, 从而避免复杂的Propose交互,也能加快reply,  PBFT也是类似的。

     

    • PBFT

                从上面来看,一次提议需要5次交互,在中心化系统中,节点之间有专线连接,时延一般较低,可能还好。但在分布式系统中,节点之间可能分布在不同的个人设备上,时延往往较大,因而需要减少交互次数。PBFT实现上就是通过广播来减少交互次数的,即Acceptor不仅仅和proposer交互还和其他Acceptor交互。Basic-Paxos下,Accepter接收到的Accept消息是Proposer统计promise消息发出来的,在PBFT下,Acceptor之间互相广播promise消息,因而自己就可以统计自己收集到的promise消息,如果超过多数promise消息就可以直接accept并发出Accepted消息。

     

     

    优化后的交互图

     

        当然在PBFT里,这些交互过程名称有所变化。propose叫做pre-prepare, promise叫做prepare, accepted叫做commit, 当节点收到2/3*n+1各节点的commit即认为数据被confirm了,可以直接reply。

     

     

        而区块链TenderMint里的PBFT协议里各个阶段的名字又不一样,propose这个名字是一样的,promise对应prevote, accepted对应precommit, 节点等到2/3*n+1个节点的precommit即认为数据被chosen(confirm), 执行commit将数据写入到区块里。

     

     

    分布式一致性协议算是一个比较复杂的系统,需要多思考讨论,欢迎文章下面留言讨论


    系列文章:

    分布式一致性协议三部曲-深入理解一致性协议

    分布式一致性协议三部曲-从paxos幽灵复现看Raft实现原理

    分布式一致性协议三部曲-PBFT源码分析

    所有的码客文章,都在这里,欢迎长按关注

    展开全文
  • 分布式一致性协议介绍

    千次阅读 2020-03-25 22:48:52
    概述 在分布式系统中,由于一个事务操作...2PC,是Two-Phase Commit的缩写,即二阶段提交,是分布式一致性协议中的一种,用于保证分布式系统中的数据一致性。顾名思义,2PC将整个事务的提交过程分为了两个阶段进行...

    概述

    在分布式系统中,由于一个事务操作需要跨越多个分布式节点,为了保持事务处理的ACID特性,所以引入了协调者参与者的概念。由协调者进行决策,参与者执行决策。并基于这种思想,衍生出2PC和3PC两种提交协议。

    2PC

    2PC,是Two-Phase Commit的缩写,即二阶段提交,是分布式一致性协议中的一种,用于保证分布式系统中的数据一致性。顾名思义,2PC将整个事务的提交过程分为了两个阶段进行操作。它们分别是:提交事务请求阶段和执行事务提交阶段

    (阶段一)提交事务请求阶段

    阶段一示例图

    1. 在上图中,协调者先向各个参与者发出一个询问请求,询问各个参与者能否执行事务提交操作,并等待参与者的回应
    2. 各个参与者收到询问后,执行事务操作,并将Undo和Redo的信息记入事务日志中
    3. 然后各个参与者根据自身情况向协调者反馈YES或者NO。YES表示事务可以执行;NO表示事务不能执行。

    至此,2PC的阶段一执行完毕,阶段二会有两种情况,我将分别叙述。

    (阶段二情况一)执行事务提交

    阶段二-情况一——提交事务

    进入该阶段的前提是所有的参与者皆返回YES响应。否则进入中断事务阶段
    
    1. 所有参与者在做完事务操作之后,向协调者反馈YES。协调者收到所有参与者的YES响应之后,向所有的参与者发出去commit请求,即表示各个参与者可以提交事务了,请求发送之后,会继续等待参与者的ACK反馈。
    2. 参与者收到 commit 请求后,开始提交事务,并在提交事务之后释放自己在这整个过程中所占有的资源。同时向协调者发送ACK反馈。
    3. 协调者收到所有参与者的ACK反馈后,整个事务完成。
    (阶段二情况二)中断事务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvtFNImp-1585147625908)(https://donkeyx.top/upload/2020/3/2pc-p2-2-83e2e53e4c404bfc8c59cd7fee411e4a.png)]

    进入该阶段的条件是有任意的参与者向协调者返回NO或者在等待过程中等待超时
    
    1. 如果有任意的参与者向协调者返回NO或者协调者等待超时(等待参与者响应),那么协调者会向所有的参与者发送Rollback请求。
    2. 参与者在收到Rollback请求后则会按照之前记录在事务日志中的Undo信息,执行事务回滚操作,然后释放自己在这整个过程中所占有的资源,同时向协调者发送ACK反馈。
    3. 协调者收到所有参与者的ACK反馈之后,整个中断事务完成。
    2PC总结

    2PC就是简单的把事务的处理过程分为了投票和执行两个阶段,它的优点就是原理简单实现方便。但是它的缺点也很明显。比如同步阻塞单点问题数据不一致太过保守等问题。

    同步阻塞 是因为在整个分布式事务的投票和执行阶段,各个参与者会等待其他参与者的响应,而在这个过程中无法做其他事情。

    单点问题是因为整个分布式事务的处理过程都是由协调者进行调控,如果协调者出现问题,那么整个系统便会不可用。

    数据不一致是因为分布式系统是通过网络进行通信,如果在阶段二,协调者发出了commit请求后,发生了局部网络异常,或者协调者未发送完commit请求后就宕机了,就会出现部分节点执行了提交事务操作,部分节点未执行提交事务操作的情况,从而导致整个分布式系统中的数据不一致的情况

    太过保守是因为在协调者和参与者 的通信过程中,如果参与者down机,协调者只会依靠超时机制来判断是否需要中断事务,而没有其他方式。

    3PC

    3PC,即3阶段提交。3PC在2PC的基础上,将提交事务请求也就是第二阶段分为了2步,同时也为参与者增加了超时机制,所以3PC也解决了一部分2PC的问题

    (阶段一)CanCommit阶段

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HWGRPsCT-1585147625910)(https://donkeyx.top/upload/2020/3/3PC-canCommit-ff8d14d847584efd9622273cd20f68ee.png)]

    1. 协调者向所有参与者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作
    2. 参与者收到canCommit请求后,根据自身情况反馈YES或者NO

    一阶段也是一个简单的投票过程,主要内容是后面两个阶段,都会分情况进行讨论

    (阶段二情况一)preCommit阶段

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o9lLo5n2-1585147625912)(https://donkeyx.top/upload/2020/3/3PC-preCommit-1-9c1cc2b5e51c4265acee24c09ca9dd5c.png)]
    如果所有的反馈都是YES,那么将进入事务预提交阶段。

    1. 协调者收到所有参与者的YES反馈后,向所有参与者发出preCommit请求,此时进入Prepared阶段
    2. 参与者收到preCommit请求后,将Undo和Redo信息记录到事务日志中,然后向协调者反馈一个ACK请求,等待最终的指令

    事务预提交阶段,完成了事务操作,并等待提交事务或者中断事务的指令

    (阶段二情况二)中断事务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SAukeNN1-1585147625914)(https://donkeyx.top/upload/2020/3/3PC-preCommit-abort-1b4b44915590492abb9f02501f470807.png)]
    如果有任意一个参与者反馈了NO或者协调者等待超时。那么将进入中断事务阶段

    1. 协调者收到NO或者等待超时,向所有参与者发送abort请求
    2. 中断事务,协调者不等待ACK响应

    在该阶段,协调者发送了abort请求后即意味着事务中断,参与者即使没有收到这个请求,也会在等待超时之后自行中断事务。

    (阶段三情况一)doCommit阶段

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T9ZzDiVR-1585147625916)(https://donkeyx.top/upload/2020/3/3PC-doCommit-cf469e9bbead4b01bfb776877fb9f579.png)]
    协调者在正常工作的前提下,并且收到了所有参与者的ACK响应,那么将会状态会从预提交转换到提交状态

    1. 协调者向所有参与者发送doCommit请求
    2. 参与者收到请求后,执行事务提交,完成后释放自己所占有的资源然后向协调者发送ACK消息
    3. 协调者收到所有参与者的ACK消息后,完成事务

    这是 第三阶段的正常完成情况

    (阶段三情况二)中断事务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZtpAKZa9-1585147625918)(https://donkeyx.top/upload/2020/3/3PC-doCommit-abort-c532b021e5ba42df83af8d2f315261db.png)]
    进入该阶段的条件同preCommit的中断事务一样,只有协调者收到任何一个参与者的NO反馈或者等待超时后仍无法收到所有参与者的响应

    这里的NO反馈,指的是doCommit阶段的NO反馈,意味着有参与者没有完成事务提交。

    1. 协调者向所有参与者发送abort请求
    2. 参与者收到abort请求后,按照事务记录日志中的Undo信息执行事务回滚操作,回滚完成后释放自己所占有的资源,然后向协调者发送ACK消息
    3. 协调者收到了所有参与者的ACK消息后,中断事务

    进入了阶段三,无论是协调者出现问题还是协调者与参与者之间出现网络故障,参与者都会在等待超时之后自动进行事务提交

    3PC 总结

    3PC优点是降低了2PC的阻塞范围,且避免了单点问题。

    展开全文
  • 常用的分布式一致性协议

    千次阅读 2020-06-02 23:42:32
    文章目录分布式一致性Base理论2PC3PCPaxos算法复制状态机强一致性PaxiosMulti PaxosRaft协议ZAB协议 分布式一致性 在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置...
  • 图解分布式一致性协议Paxos, 从 slideshare 上搬运过来的,非常不错的讲解,适合对 paxos 感兴趣的开发人员
  • 分布式一致性协议:Raft算法详解

    万次阅读 2019-05-24 21:37:40
    在分布式系统中,有很多复杂的理论,从CAP理论到BASE理论,我们不断的在可用性以及一致性之间做出抉择,每一部分都相当复杂,就分布式一致性而言,又有许多协议,从2PC到3PC再到paxos算法,到ZAB协议,再到Raft算法...
  • paxos-分布式一致性协议.pdf 知行学社 PPT
  • 文章目录分布式事务理论ACIDCAPBASEPaxoszookeeper基本概念...一致性 数据库在事务执行前和执行后都处于一致性的状态。避免执行过程中的故障导致数据的不一致 隔离性 并发的事务不能彼此干扰。在标准的sql规范中定...
  • 文章目录前言CAP理论分布式一致性协议协议的几个规则数据复制领导者选举如何保证一致性总结回答开篇 前言 在分布式开发中,我认为具备CAP理论与了解Raft、Zab等分布式一致性协议是十分有必要的,例如分布式锁的选择...
  • 分布式一致性协议Raft & Paxos 简单 v.s. 完美
  • raft协议的作者讲解raft协议的ppt,强烈推荐,B站有配合该ppt的视频讲解,
  • #资源达人分享计划#
  • 基于Raft分布式一致性协议实现的局限及其对数据库的风险.docx
  • Zookeeper中的分布式一致性协议ZAB

    万次阅读 2020-10-27 17:24:33
    分布式系统中的一致性协议分布式系统中,分布式理论CAP中的P(分区容忍性)是必然存在的,所以需要在C(一致性)和A(可用性)之间进行取舍。而在很多系统中,引入分布式完全是为了解决单机的单点故障问题,引入...
  • 分布式一致性协议 二阶段提交协议(2pc)三阶段提交协议(3pc)paxoszab 在分布式系统中,每个机器都可以确定自己进行的事务操作是否成功,但是无法直接了解其他机器的操作结果。因此,当一个分布式事务操作...
  • 行业分类-设备装置-基于分布式一致性协议实现的数据读写方法及装置
  • 中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议的一致性。 主要有三类节点: 提议者(Proposer):提议一个值; 接受者(Acceptor):对每个提议进行投票; 告知者(Learner):被...
  • 分布式系统---分布式一致性协议

    千次阅读 2016-10-25 13:07:21
    两阶段提交协议 三阶段提交协议 Paxos算法 zookeeper一致性协议:zab
  • 《Paxos Made Simple》分布式一致性协议Paxos论文翻译
  • 第三章:深入浅出理解分布式一致性协议Gossip和Redis集群原理 Redis是一个开源的,高性能的 key-value 的数据库。基于 Redis 的分布式缓存已经有很多成功的商业应用,其中就包括阿里 ApsaraDB,阿里Tair中的rdb引擎...
  • 由于毕设和Lab项目需要,最近在看《从paxos到zookeeper分布式一致性原理与实践》, 2和3PC算法流程,网上资料很多,就不赘述了。由于书中关于2PC和3PC的缺点的部分描述不容易让人理解,因此本文主要想讨论一下2和3PC...
  • 分布式一致性算法Raft协议的学习记录,
  • 分布式一致性协议之TCC。

    千次阅读 2019-02-11 11:15:55
    二阶段提交协议和三阶段提交协议,实际上他们能解决分布式事务的问题,但是遇到极端情况时,系统会产生阻塞或者不一致的问题,需要运营或者技术人员解决。两阶段及三阶段方案都包含多个参与者、多个阶段实现一个事务...
  • 分布式一致性协议-2PC与3PC(三)

    万次阅读 2018-05-16 22:03:03
    一、分布式一致性 一个事务需要跨多个分布式节点,又要保持事务的ACID特性,需要引入协调者来统一调度所有分布式节点的执行逻辑,被调度的节点称为参与者。 协调者负责调用参与者,并决定最终是否提交事务。基于这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 144,275
精华内容 57,710
关键字:

分布式一致性协议