分布式事务

117 阅读15分钟

总图: image.png

1 基础理论部分

1.1 CAP

  • C:一致性,区分为三个等级:强一致性、弱一致性与最终一致性。
  • A:可用性,在有限时间内返回正常结果
  • P: 分区容错性,在某分区出现故障后,仍能对外提供一致性和可用性的服务 三者最多同时满足两项,在大多数应用场景中,都需要牺牲强一致性来换取系统的高可用性。

1.2 BASE理论

根据CAP定理演化而来,核心思想在于急事无法做到强一致性,但每个业务也可以根据自身业务特点,采用适当的方法来达到最终一致性
  • Bascially Available 基本可用:在系统发生不可预知的故障的时候,允许损失部分可用性,但是不等于系统完全不可用
  • Soft state 软状态 :允许系统中的数据处于中间状态,并且认为中间状态的存在不会影响系统的整体可用性
  • Eventually consistent :系统中所有的数据副本,在经过一段时间后,都能打到最终一致的状态。

2 刚性事务

2.1 XA规范

  • X/OPEN国际联盟有限公司,它的建立时为了向UNIX环境提供标准,促进对UNIX语言、接口、网络和应用的开放式系统协议的制定。
  • X/OPEN DTP(Distributed Transaction Process)是一个分布式事务模型,主要使用两段提交(2PC)来保证分布式事务的完整性。
  • XA规范是X/OPEN组织定义的分布式事务处理标准,规范了全局的事务管理器和资源管理器之间的接口,它的目的是允许多个资源可以在同一事务中访问,可以使ACID属性跨越应用程序的同时保证有效。
  • XA是数据库的分布式事务,具有强一致性,在整个过程中,TM始终把持着数据库的锁,如果期间其他线程要修改数据库中该条数据,就必须等待锁的释放,存在着长事务的风险。

image.png XA有两大限制:必须拿到所有的数据源,并且数据源还要支持XA协议;性能比较差,需要锁住所有涉及到的数据,会产生长事务。

2.2 Seata AT 模式

增强版2PC模式,将事务分为两个阶段:一阶段将业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和链接资源;二阶段 提交异步化,非常快速地完成,或回滚第一阶段的回滚日志进行反向补偿。

2.3 LCN(2PC)

TX-LCN是一款事务协调性框架,本身并不生产事务,而是本地事务的协调者,从而达到事务一致性的效果。

顾名思义,2PC需要分两个阶段进行处理:阶段一提交事务请求,阶段2 执行事务提交。若阶段1 出现超时或异常,则阶段二中断事务。

  • 阶段1

提交事务请求:1、事务查询。协调者向所有参与者发送事务内容,询问是否可以执行提交操作,并开始等待各参与者进行响应;2、执行事务:各参与者节点执行事务操作,并将undo和redo操作计入本机事务日志;3、各参与者向协调者反馈事务问询的响应,成功执行返回yes,否则返回no

  • 阶段2:执行事务提交

协调者决定是否最终执行事务的提交操作,若所有的执行者都返回yes,则执行事务提交:发送提交请求 -> 事务提交,并释放期间占用的资源 -> 反馈提交结果,向协调者发送ACK消息确认 -> 完成事务,协调者收到所有参与者的ACK消息后,最终完成事务

  • 阶段二:中断事务

当某一个参与者向协调者发送no响应,或者等待超时,则中断事务。1、发送回滚请求,向所有的参与者发送RollBack请求 2、回滚,参与者收到信息后,利用本机的undo信息,执行回滚操作,并释放资源 3、反馈回滚结果 4、中断事务

2.3.1 2PC的优缺点

优点在于实现原理简单,但是缺点比较多

  • 在事务的执行过程中,所有的参与事务操作的逻辑都处于阻塞状态
  • 协调者是个单点,若出问题,其他参与者无法释放事务资源,也无法完成事务操作
  • 数据不一致,在执行事务提交的过程中,若某条消息丢失掉,则整个系统将出现数据不一致的情形
  • 保守,没有完善的容错机制,一旦出现问题,只能回滚

2.4 3PC

3PC将2PC的过程扩展为了三个过程:

  • 阶段一 : CanCommit

事务询问,询问各个参与者是否可以执行事务提交,并等待应答 -> 各参与者反馈事务询问,返回YES / NO

  • 阶段二 :PreCommit 执行事务预提交 发送预提交请求 -> 事务预提交 -> 各参与者成功执行事务操作,并将反馈以ACK响应形式发送给协调者,等待最终的Commit或Abort命令。

  • 阶段二: PreCommit 中断事务

任意一个参与者发送了NO请求,或者等待超时了 协调者就 发送中断请求,并中断事务。

  • 阶段三:doCommit 执行提交 当协调者收到所有参与者的ACK响应后,将预提交状态转化为提交状态,并向所有的参与者发送doCommit请求;参与者收到后,执行正式的提交请求,并释放资源,向协调者发送ACK响应; 协调者收到所有的ACK响应后,最终完成事务

  • 阶段三:doCommit 中断事务 若在该阶段,收到任意一个no响应,或者等待超时,则中断事务。协调者向所有的参与者发送abort,参与者收到后,利用undo回滚消息,释放资源;回滚完毕后,向协调者发送ack响应;协调者收到所有的ack消息后,完成事务中断。

3PC 相对于 2PC优化的地方

  • 3PC对协调者和参与者都设置了一个超时时间,避免了参与者长时间无法与协调者节点通讯的情况下,无法释放资源的情况。另外,多设置了一个缓冲阶段,进一步保证在最终提交阶段之前各参与节点的状态一致。

3 柔性事务

柔性事务具有两大特性:基本可用 和 柔性状态;主要分为两种:补偿性和通知型

3.1 通知型事务

通知型事务主要是通过MQ来通知其他事务参与者自己事务的执行状态,各参与者异步执行,所以也被称为异步事务。主要用于需要异步更新数据,并对数据的实时性要求不高的场景。

  • 异步确保型事务:主要适用于内部系统的数据最终一致性保障,如订单和购物车、收货与结算等
  • 最大努力通知:主要用于外部系统,因为外部的网络环境更加复杂和不可信,只能尽最大努力去通知,实现数据最终一致性,如充值平台与运营商等。

3.2 异步确保型事务

3.2.1 半步消息机制来实现异步事务

  • 半消息机制:在原有队列消息执行后的逻辑,如果后面的本地逻辑出错,则不发送消息,如果通过,则告知MQ发送。 依靠MQ的半消息机制来实现投递消息和参与者自身本地事务的一致性保障,借鉴了2PC的思路,可以看作是它的广义拓展。
  1. 事务发起方首先发送半消息到MQ
  2. MQ通知发起方信息发送成功
  3. 半消息发送成功后执行本地事务
  4. 根据本地事务的执行结果返回commit或rollback
  5. 如果rollback,回滚,如果commit,MQ发送消息给消息订阅方
  6. 订阅方根据消息执行本地事务
  7. 本地事务执行成功,在MQ中将消息标记为已消费
  8. 如果在执行本地事务的过程中,执行端挂掉或超时,MQ服务器将不停询问消息生产者来获取事务状态
  9. Consumer端的消息成功机制由MQ保证。

3.2.2 基于阿里的RocketMQ实现MQ异步确保型事务

常见的消息中件键中,ActiveMQ 与 RocketMQ支持事务,但是Kafka 与 RabbitMQ 不支持异步事务。

在这里大致描述一下整体的过程: 1. 1. 1. ……

3.3本地消息表方案

当目前使用的MQ组件不支持分布式事务的时候,就得找到一个尽量少的侵入业务方,即 基于DB本地消息表 ,它的核心思想就是把分布式事务拆分为本地事务进行处理。

3.3.1 消息发送方

  • 需要一个消息表,记录消息状态信息
  • 业务数据和消息表同处于一个数据库中,利用本地事务来将业务数据和消息数据直接写入数据库
  • 本地事务处理完消息数据和业务数据后,通过写消息到MQ消息队列,使用专门的投递工作线程将事务消息传递给MQ,根据返回的ACK删除事务消息表数据
  • 消息发送到消费方,若失败,则重试

3.3.2 消息消费方

  • 处理消息队列中的消息,完成自己的业务逻辑
  • 若本地事务处理成功,则表示已经处理成功了
  • 若本地事务失败,则重新执行
  • 如果是业务层面的失败,给消息生产方发送一个业务补偿信息,通知进行回滚等操作。

3.3.3 本地消息表的优缺点

优点

  • 建设成本低,实现了可靠消息的传递,确保了分布式事务的最终一致性
  • 无需提供回查操作,进一步减少业务的侵入
  • 在某些场景下,可以进一步利用注释等形式进行解耦,实现无业务代码侵入的实现

缺点

  • 本地消息表与业务耦合在一起,难于做成通用性,不可独立伸缩
  • 本地消息表基于数据库来实现,因此在高并发下,具有性能瓶颈问题

image.png

3.4 最大努力通知

通知型事务的难点在于:投递消息和参与者本地事务的一致性保障 核心都是为了保证消息的一致性投递,所以它的解决办法也有两个分支:基于MQ消息队列实现、基于DB本地事务消息表实现。

3.4.1 MQ事务消息方案实现最大努力通知

特性

  • 业务主动方完成业务处理后,向业务被动方发送消息,允许存在消息丢失
  • 业务主动方提供递增挡位时间间隔,若发送失败则重试,通知N次后,报警、记录日志、人工干预
  • 业务被动方提供幂等性的服务接口,防止消息的重复消费
  • 业务主动方需要有定期校验机制,对业务数据兜底,确保数据的最终一致性
  • 被动方的结果不影响主动官方的处理结果
  • 适用于对业务最终一致性的时间敏感度较第的系统

3.4.2 本地消息表方案实现最大努力通知

多加一个步骤:生产方定时扫描本地消息表,把还没处理的消息或失败的消息再发送一遍。 特点 : 与上相同

3.5 最大努力通知事务与异步确保型事务的区别

  • 从业务适合度上讲,异步确保型事务适合于同网络体系的内部服务支付,而最大努力通知事务,适合于跨平台、跨企业的系统间使用
  • 从消息层面来将,异步确保型事务只需要消息消费者主动去消费就可以了 ,但是最大努力通知事务需要主动推送,并提供多挡次时间的重试机制来保证消息数据的通知
  • 从数据的层面,异步确保型事务只需要保证消息的可靠传递即可;但最大努力通知事务需要额外的定期校验机制对数据进行兜底,保证数据的最终一致性。

4 补偿型模式实现

通知型业务不能解决所有的业务场景,所以引入了补偿型的业务:使用一个额外的协调服务来协调各个需要保证一致性的业务服务,协调服务按照顺序调用各个业务微服务,若某一个出现异常,则取消之前所有已经调用成功的业务。 只要有两种实现模式:TCC 和 Saga

4.1 TCC分布式事务模型

  • 主业务服务:整个业务的发起方,服务的编排者,负责发起并完成整个业务服务
  • 从业务服务:整个业务的参与方,负责提供TCC业务操作:初步操作Try ,确认操作Confirm , 取消操作Cancel ,供主业务服务调用。
  • 业务活动管理器:业务活动管理器管理控制整个业务活动,包括记录维护TCC全局事务的事务状态和每个从业务服务的子事务状态,并在业务活动提交时调用所有从业务的Confirm操作,再业务活动取消时调用所有从业务的cancel操作。

4.2 TCC事务模型的要求:

  • 1、可查询:服务操作具有全局唯一的标识,操作唯一的确定的时间
  • 2、幂等操作
  • 3、TCC操作: Try阶段,尝试执行业务,完成所有业务的检查,实现一致性,并预留必须的业务资源,实现隔离性;confirm阶段,真正去执行业务,不做任何检查,还得满足幂等性;cancel操作,取消执行业务,释放try阶段预留的业务资源,也需要满足幂等性。
  • 4、可补偿操作:Do阶段,真正执行业务处理,处理结果外部可见;Compensate阶段:抵消或者部分撤销正向业务操作的业务结果,补偿操作满足幂等性。约束:补偿操作在业务上可行,由于业务执行结果未隔离,或者补偿不完整带来的风险和成本可控。

4.3 TCC 与 2PC的不同之处

  • XA是资源层面上的分布式事务,强一致性,在整个提交过程中,一直持有资源的锁。基于数据库支持XA协议,由于在执行事务的全程都需要对相关数据加锁,所以高并发情况下性能较差
  • TCC是业务层面上的分布式事务,只保证了最终一致性,不会一直持有资源的所 ,性能较好,但是侵入性强,每个事务都得实现TCC三个方法,开发、维护成本高。且必须实现幂等性操作,必然损耗一定的性能,拉长业务的时间。

5 Sage长事务模型保证柔性一致性

Sage模型把一个分布式事务拆分为多个本地事务,每个本地事务都有自己对应的执行和补偿模块。当某个本地事务出错后有,调用相应的补偿方法恢复到之前的业务。
**牺牲了一定的隔离性和一致性,但提高了长事务的可用性**

5.1 Sage模型的三个组成部分

  • LLT(Long Live Transaction):由本地事务组成的事务链。
  • 本地事务
  • 补偿:每个本地事务都有对应的补偿。

5.1.1 Saga执行顺序

  • T1 、 T2 、T3 、 T4 、 Tn
  • T1 、 T2 、T3 、 T4 、 Tn 、 C3 、 C2 、 C1

5.1.2 Saga两种恢复策略

  • 向后恢复 , 撤销掉之前成功的所有成功子事务,如果任意本地子事务失败,则补偿已完成的事务
  • 向前恢复 , 重试失败的事务,适用于必须得成功的业务。若失败,则一直重试,真不行的话,就人工干预

5.1.3 Sage的使用条件

  • 只允许两个层次的嵌套,顶级Saga和简单子事务
  • 在外层的全原子性不能得到满足,也就是Sagas可能会看到其他的sagas的部分结果
  • 每个子事务应该是独立的原子行为
  • 补偿事务从语义角度撤销了事务Ti的行为,但未必能将数据库返回到执行Ti时的状态。

5.2 Saga模型的解决方案

  • 半消息模式(消息队列与数据库)
  • 本地消息表(向本地业务表和消息表中插入数据)

5.3 Saga与TCC对比

Saga相对于TCC,缺少预留动作,导致补偿动作的实现比较麻烦,但是减少了通讯次数,并且某些第三方服务没有Try接口,使用TCC实现的话 ,就比较麻烦;且没有预留动作,也意味着不必担心资源释放问题,异常处理更加简单。

TCC与Saga都是补偿性事务,无法保证隔离性

image.png

6 分布式解决工具 |: Seata

Seata提供了四种解决方案: AT、TCC、Saga 和 XA事务模式

6.1 Seaga AT 模式

增强型二阶段提交实现 …………(待补充)