分布式技术架构原理解析之协调与同步(四)分布式事务

概述

通常我们在网上商城购物,对于每一笔订单交易来说,一般会有两个核心的步骤:

  • 订单业务:下订单操作
  • 库存业务:减库存操作
    订单业务和库存业务一般会运行在不同的机器上,甚至是运行在不同区域的机器上。针对同一笔订单,当且仅当订单操作和减库存操作一致时,才能保证交易的正确性。也就是说一笔订单,只有这两个操作都完成,才能算做处理成功,否则处理失败,在分布式领域中,这个问题就是分布式事务问题。

1、什么是分布式事务

事务,其实是包含一系列操作的、一个有边界的工作序列,有明确的开始和结束标志,且要么被完全执行,要么完全失败,即 all or nothing。通常情况下,我们所说的事务指的都是本地事务,也就是在单机上的事务。
事务的特征 ACID,也是分布式事务的基本特征,其中 ACID 具体含义如下:

  • 原子性(Atomicity),即事务最终的状态只有两种,全部执行成功和全部不执行。若处理事务的任何一项操作不成功,就会导致整个事务失败。一旦操作失败,所有操作都会被取消(即回滚),使得事务仿佛没有被执行过一样。
  • 一致性(Consistency),是指事务操作前和操作后,数据的完整性保持一致或满足完整性约束。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元 ; 一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况。
  • 隔离性(Isolation),是指当系统内有多个事务并发执行时,多个事务不会相互干扰,即一个事务内部的操作及使用的数据,对其他并发事务是隔离的。
  • 持久性(Durability),也被称为永久性,是指一个事务完成了,那么它对数据库所做的更新就被永久保存下来了。即使发生系统崩溃或宕机等故障,只要数据库能够重新被访问,那么一定能够将其恢复到事务完成时的状态。
    分布式事务,就是在分布式系统中运行的事务,由多个本地事务组合而成。基本能够满足 ACID,其中的 C 是强一致性,也就是所有操作均执行成功,才提交最终结果,以保证数据一致性或完整性。但随着分布式系统规模不断扩大,复杂度急剧上升,达成强一致性所需时间周期较长,限定了复杂业务的处理。为了适应复杂业务,出现了 BASE 理论,该理论的一个关键点就是采用最终一致性代替强一致性。
    BASE 理论包括基本可用(Basically Available)、柔性状态(Soft State)和最终一致性(Eventual Consistency)。
  • 基本可用:分布式系统出现故障的时候,允许损失一部分功能的可用性。
  • 柔性状态:在柔性事务中,允许系统存在中间状态,且这个中间状态不会影响系统整体可用性。比如,数据库读写分离,写库同步到读库(主库同步到从库)会有一个延时,其实就是一种柔性状态。
  • 最终一致性:事务在操作过程中可能会由于同步延迟等问题导致不一致,但最终状态下,数据都是一致的。
    可见,BASE 理论为了支持大型分布式系统,通过牺牲强一致性,保证最终一致性,来获得高可用性,是对 ACID 原则的弱化。

2、分布式事务实现

分布式事务主要是解决在分布式环境下,组合事务的一致性问题。实现分布式事务有以下 3 种基本方法

  • 基于 XA 协议的二阶段提交协议方法:强一致性
  • 三阶段提交协议方法:强一致性
  • 基于消息的最终一致性方法:最终一致性

2.1基于 XA 协议的二阶段提交方法

2.1.1 XA 协议的二阶段提交方法

XA 是一个分布式事务协议,规定了事务管理器和资源管理器接口。可以分为两部分,即事务管理器和本地资源管理器。
其中事务管理器作为协调者,负责各个本地资源的提交和回滚;而资源管理器就是分布式事务的参与者,通常由数据库实现,比如 Oracle、DB2 等商业数据库都实现了 XA 接口。
基于 XA 协议的二阶段提交方法中,二阶段提交协议(The two-phase commit protocol,2PC),用于保证分布式系统中事务提交时的数据一致性,是 XA 在全局事务中用于协调多个资源的机制。

2.1.2 实现过程

通过两阶段提交协议来保证分布式系统在不同节点上的分布式事务的一致性,需要引入一个协调者来管理所有的节点,并确保这些节点正确提交操作结果,若提交失败则放弃事务。
两阶段提交协议的具体过程分为投票(voting)和提交(commit)两个阶段。

  • 第一阶段投票:协调者(Coordinator,即事务管理器)会向事务的参与者(Cohort,即本地资源管理器)发起执行操作的 CanCommit 请求,并等待参与者的响应。参与者接收到请求后,会执行请求中的事务操作,记录日志信息但不提交,待参与者执行成功,则向协调者发送“Yes”消息,表示同意操作;若不成功,则发送“No”消息,表示终止操作。

  • 第二阶段,提交:当所有的参与者都返回了操作结果(Yes 或 No 消息)后系统进入了提交阶段,在提交阶段,协调者会根据所有参与者返回的信息向参与者发送 DoCommit 或 DoAbort 指令:

  • 若协调者收到的都是“Yes”消息,则向参与者发送“DoCommit”消息,参与者会完成剩余的操作并释放资源,然后向协调者返回“HaveCommitted”消息;

  • 如果协调者收到的消息中包含“No”消息,则向所有参与者发送“DoAbort”消息,此时发送“Yes”的参与者则会根据之前执行操作时的回滚日志对操作进行回滚,然后所有参与者会向协调者发送“HaveCommitted”消息;

  • 协调者接收到“HaveCommitted”消息,就意味着整个事务结束了
    二阶段提交的算法思路可以概括为协调者下发请求事务操作,参与者将操作结果通知协调者,协调者根据所有参与者的反馈结果决定各参与者是要提交操作还是撤销操作

2.1.3 二阶段提交算法的不足

  • 同步阻塞问题:二阶段提交算法在执行过程中,所有参与节点都是事务阻塞型的。也就是说,当本地资源管理器占有临界资源时,其他资源管理器如果要访问同一临界资源,会处于阻塞状态。
  • 单点故障问题:基于 XA 的二阶段提交算法类似于集中式算法,一旦事务管理器发生故障,整个系统都处于停滞状态。尤其是在提交阶段,一旦事务管理器发生故障,资源管理器会由于等待管理器的消息,而一直锁定事务资源,导致整个系统被阻塞。
  • 数据一致性问题:在提交阶段,当协调者向参与者发送 DoCommit 请求之后,如果发生了局部网络异常,或者在发送提交请求的过程中协调者发生了故障,就会导致只有一部分参与者接收到了提交请求并执行提交操作,但其他未接到提交请求的那部分参与者则无法执行事务提交。于是整个分布式系统便出现了数据不一致的问题。

2.2三阶段提交方法

2.2.1 三阶段提交方法

三阶段提交协议(Three-phase commit protocol,3PC),解决了两阶段提交的同步阻塞和数据不一致问题,三阶段提交引入了超时机制和准备阶段。

  • 同时在协调者和参与者中引入超时机制。如果协调者或参与者在规定的时间内没有接收到来自其他节点的响应,就会根据当前的状态选择提交或者终止整个事务。
  • 在第一阶段和第二阶段中间引入了一个准备阶段,也就是在提交阶段之前,加入了一个预提交阶段。在预提交阶段排除一些不一致的情况,保证在最后提交之前各参与节点的状态是一致的。

2.2.2 三阶段提交方法实现过程

除了引入超时机制之外,3PC 把 2PC 的提交阶段一分为二,这样三阶段提交协议就有 CanCommitPreCommitDoCommit 三个阶段:
第一阶段:CanCommit 阶段

  • 协调者向参与者发送请求操作(CanCommit 请求),询问参与者是否可以执行事务提交操作,然后等待参与者的响应;
  • 参与者收到 CanCommit 请求之后,回复 Yes,表示可以顺利执行事务;
  • 否则回复 No。
    CanCommit 阶段不同节点之间的事务请求成功和失败的流程,如下所示:
    分布式技术架构原理解析之协调与同步(四)分布式事务_第1张图片
    第二阶段: PreCommit 阶段
    协调者根据参与者的回复情况,来决定是否可以进行PreCommit 操作。
    1.如果所有参与者回复的都是“Yes”,那么协调者就会执行事务的预执行:
  • 发送预提交请求:协调者向参与者发送 PreCommit 请求,进入预提交阶段。
  • 事务预提交:参与者接收到 PreCommit 请求后执行事务操作,并将 Undo 和 Redo 信息记录到事务日志中。
  • 响应反馈:如果参与者成功执行了事务操作,则返回 ACK 响应,同时开始等待最终指令。
    2.假如任何一个参与者向协调者发送了“No”消息,或者等待超时之后,协调者都没有收到参与者的响应,就执行中断事务的操作:
  • 发送中断请求:协调者向所有参与者发送“Abort”消息。
  • 中断事务:参与者收到“Abort”消息之后,或超时后仍未收到协调者的消息,执行事务的中断操作。
    预执行阶段,不同节点上事务执行成功和失败的流程,如下所示:
    分布式技术架构原理解析之协调与同步(四)分布式事务_第2张图片
    第三阶段:DoCommit 阶段
    DoCmmit 阶段进行真正的事务提交,根据 PreCommit 阶段协调者发送的消息,进入执行提交阶段或事务中断阶段。
    1.执行提交阶段
  • 发送提交请求:协调者接收到所有参与者发送的 Ack 响应,从预提交状态进入到提交状态,并向所有参与者发送 DoCommit消息。
  • 事务提交:参与者接收到 DoCommit消息之后,正式提交事务。完成事务提交之后,释放所有锁住的资源。
  • 响应反馈:参与者提交完事务之后,向协调者发送 Ack响应。
  • 完成事务:协调者接收到所有参与者的 Ack 响应之后,完成事务。
    2.事务中断阶段
  • 发送中断请求:协调者向所有参与者发送 Abort 请求。
  • 事务回滚:参与者接收到 Abort 消息之后,利用其在 PreCommit阶段记录的 Undo 信息执行事务的回滚操作,并释放所有锁住的资源。
  • 反馈结果:参与者完成事务回滚之后,向协调者发送 Ack消息。
  • 中断事务:协调者接收到参与者反馈的 Ack 消息之后,执行事务的中断,并结束事务。
    执行阶段不同节点上事务执行成功和失败 (事务中断) 的流程,如下所示:
    分布式技术架构原理解析之协调与同步(四)分布式事务_第3张图片

2.2.3 三阶段提交方法小结

当参与者向协调者发送 Ack 消息后,如果长时间没有得到协调者的响应,在默认情况下,参与者会自动将超时的事务进行提交,不会像两阶段提交那样被阻塞住
但是,2PC 和 3PC 这两种方法,有两个共同的缺点,一是都需要锁定资源,降低系统性能;二是,没有解决数据不一致的问题。

2.3 基于分布式消息的最终一致性方案

由于二段和三段都没有解决一致性的问题,所以有了分布式消息来确保事务最终一致性的方案。
在分布式系统架构中,解决一致性问题的核心思想就是:需要将分布式处理的事务通过消息或者日志的方式异步执行,消息或日志可以存到本地文件、数据库或消息队列中,再通过业务规则进行失败重试。这个就是使用基于分布式消息的最终一致性方案解决了分布式事务的问题,其引入了一个消息中间件(Message Queue,MQ),用于在多个应用之间进行消息传递。
基于消息中间件协商多个节点分布式事务执行操作的示意图,如下所示。
分布式技术架构原理解析之协调与同步(四)分布式事务_第4张图片
以网上购物为例,根据基于分布式消息的最终一致性方案,用户 A 通过终端手机首先在订单系统上操作,然后整个购物的流程如下所示:
分布式技术架构原理解析之协调与同步(四)分布式事务_第5张图片

2.4 三种分布式事务实现方式对比

分布式技术架构原理解析之协调与同步(四)分布式事务_第6张图片

3 总结

分布式技术架构原理解析之协调与同步(四)分布式事务_第7张图片

你可能感兴趣的:(云计算,分布式存储系统)