微服务的分布式事务解决方案

微服务的分布式事务解决方案

说起微服务的架构,分布式事务是一道绕不开的话题。本文将从分布式事务的理论模型、分布式事务的常见解决方案、分布式事务中间件 Seata的两个常用模式展开说说分布式事务。

1、分布式事务的理论模型

两阶段提交协议、三阶段提交 ,作为 XA 协议解决分布式数据一致性问题的基本原理。

1.1、X/Open 分布式事务模型

X/Open DTP 是 X/Open 定义的一套分布式事务标准,该标准使用两阶段提交来保证分布式事务的完整性。

X/Open DTP 中包含三种角色

  • ① Application(AP):指应用程序。
  • ② Resource Manager(RM):指资源管理器,比如数据库。
  • ③ Transaction Manager(TM):指事务管理器,事务协调者,负责协调和管理事务,提供AP编程接口或管理RM.

1.2、两阶段提交协议

两阶段提交协议的执行流程:

  • 准备阶段:TM 通知 RM 准备分支事务,记录事务日志,并告知 TM 的准备结果。
  • 提交/回滚阶段
    • 如果所有的 RM 在准备阶段都明确返回成功,则 TM 向所有的 RM 发起事务提交指令,完成数据变更。
    • 反之,如果任何一个 RM 明确返回失败,则 TM 会向所有 RM 发送事务回滚指令。

两阶段提交的缺点

  • 同步阻塞

    • 所有参与的 RM 都是事务阻塞型,对于任何一次指令都必须有明确的响应,才能继续进行下一步。
    • 否则会处于阻塞状态,占用的资源一直被锁定。
  • 过于保守:任何一个节点失败都会导致数据回滚。

  • TM 的单点故障:如果 TM 在第二阶段出现故障,那其他参与的RM 会一直处于锁定状态。

  • "脑裂" 导致数据不一致问题:第二阶段中 TM 向所有的 RM 发送 commit 请求后,发生局部网络异常,导致只要一部分 RM 接收到 commit 请求,进而执行了 commit 操作。另一部分 RM 未收到 commit 请求,从而事务无法提交,导致数据不一致问题发生。

1.3、三阶段提交协议

**三阶段提交协议执行流程**如下:

  • CanCommit(询问阶段):TM 向 RM 发送事务执行请求,询问是否可以完成指令,RM 只需要回答是或者不是即可,不需要做真正的事务操作,该阶段会有超时中止机制。

  • PreCommit(准备阶段):TM 会根据所有 RM 的反馈结果决定是否继续执行。

    • 如果在 CanCommit 阶段所有 RM 都返回可以执行操作,则 TM 会向所有 RM 发送 PreCommit 请求,所有 RM 收到请求后写 redo 和 undo 日志执行事务操作但不提交事务,然后返回 ACK 响应等待 TM 的下一步通知。
    • 如果在 CanCommit 阶段,任意 RM 返回不能执行操作的结果,那 TM 会向所有参与者发送事务中断请求。
  • DoCommit(提交或回滚阶段):该阶段根据 PreCommit 阶段执行的结果,来决定 DoCommit 的执行方式。

    • 如果每个 RM 在 PreCommit 阶段都返回成功,那么 TM 会向所有 RM 发起事务提交指令。
    • 如果任何一个 RM 返回失败,那么 TM 会发起中止指令来回滚事务。

相对于二阶段提交协议,三阶段提交协议利用超时机制,解决了同步阻塞问题。两者的区别如下:

  • ① 增加了 CanCommit 阶段,用于询问所有 RM 是否可以执行事务操作并响应,其目的是可以尽早发现无法执行操作而中止后续的行为
  • 在准备阶段之后 ,TM 和 RM 都引入了超时机制,一旦超时TM 和 RM 会继续提交事务,并且认为处于成功状态 ,因为在超时情况下事务默认成功的可能性比较大。超时机制避免了资源的永久锁定

2、分布式事务常见解决方案

2.1、TCC补偿型方案

TCC(Try-Confirm-Cancel)是一种两阶段提交的思想,也是一种比较成熟分布式事务一致性解决方案。TCC 补偿型方案将一个完整事务分为三个步骤:

  • Try :该阶段主要是对数据的校验,或者资源的预留。
  • Confirm :该阶段确认真正执行的任务,只操作 Try 阶段预留的资源。
  • Cancel :该阶段是取消执行,释放 Try 阶段预留的资源。

注意:在某些特殊场景下,比如服务器突然宕机,导致该服务并没有收到 TCC 事务协调器的 Cancel 或者 Confirm 请求,这时 TCC 事务框架会记录一些分布式事务的操作日志,保存分布式事务运行的各个阶段和状态。TCC 事务协调器会根据操作日志进行重试,以达到数据的最终一致性

TCC 服务支持接口调用失败发起重试,所以 TCC 暴露的接口都需要满足幂等性

2.2、基于可靠性消息的最终一致性方案

RocketMQ 事务消息模型最核心的机制,就是事务回查。下图可以看出,在 RocketMQ 事务消息模型中,事务是由生产者完成。消息队列的可靠性投递机制,保证了消费者如果没有签收消息,消息队列服务器会重复投递。具体可以参考博文 《RocketMQ 顺序消息和事务消息及其原理》 的 【RocketMQ 的事务消息】部分。

2.3、最大努力通知型方案

最大努力通知 也被称为定期校对,是以上【基于可靠性消息的最终一致性方案】的优化版,其引入了本地消息表来记录错误消息 ,然后加入失败消息的定期校对功能 ,来进一步保证消息被下游系统消费。

最大努力通知方案步骤:

  • 第一步:消息由系统A投递到中间件

    • ① 业务处理中,操作业务数据入库时,在同一事务中向本地消息表中写一条数据,且数据状态为【未发送】。
    • ② 一般采用定时任务,轮询本地消息表中【未发送】状态的数据,将这部分数据发送到消息中间件。
    • ③ 消息中间件收到消息后,通过消息中间件的返回应答状态,修改本地消息表状态为【发送成功】。
  • 第二步:消息中间件投递到系统B

    • ① 消息中间件收到第一步的消息后,同步投递给相应的下游系统,并触发下游系统的业务执行。
    • ② 当下游系统业务处理成功后,向消息中间件反馈确认应答,消息中间件便可以将消息删除,从而完成该事务。
    • ③ 对于投递失败的消息,利用重试机制进行重试,对于重试失败的,写入错误消息表。
    • ④ 消息中间件需要提供失败消息的查询接口,下游系统会定期查询失败消息。

最大努力通知方案缺点:消息表会耦合到业务系统中,如果没有封装好的解决方案,会增加系统的复杂度。

3、分布式事务中间件 Seata

Seata 组件作为一种分布式解决方案,提供了 AT、TCC、Saga 和 XA 事务模型。

3.1、AT 模式

AT 模式是基于 XA 模式演化而来的,AT 和 XA 都是两阶段事务模型,但是 AT 和XA 相比,做了很多优化。AT 模式作为 Seata 最主推的分布式事务解决方案。

AT 模式由 TM、RM 和 TC 三大模块组成,其中 TM 和 RM 作为客户端与业务系统(Application)集成,TC 作为 Seata 的服务器独立部署。AT 模式的执行流程:

  • ① TM 向 TC 注册全局事务,并生成全局唯一的 XID.
  • ② RM 向 TC 注册分支事务,并将其纳入该 XID 对应的全局事务范围。
  • ③ RM 向 TC 汇报资源的准备状态。
  • ④ TC 汇总所有事务参与者的执行状态,决定分布式事务是全部回滚还是提交。
  • ⑤ TC 通知所有 RM 提交/回滚事务。

Seata的AT模式在性能、一致性模型、侵入性、依赖性和灵活性以及配置和部署等方面,相对于XA模式进行了显著的改进。这些改进使得AT模式成为了一种更加高效、易用和灵活的分布式事务解决方案。

1. 性能提升

  • 资源锁定周期缩短:XA模式一阶段不提交事务,锁定资源直到二阶段结束才释放,这可能导致性能瓶颈。而AT模式一阶段直接提交事务,不锁定资源,从而缩短了资源锁定周期,提高了系统性能。
  • 减少数据库交互:AT模式通过记录数据快照(undo log)来实现回滚,减少了与数据库的交互次数,进一步提升了性能。

2. 一致性模型

  • 最终一致性 vs 强一致性:XA模式遵循两阶段提交协议,保证事务的强一致性(满足ACID原则)。而AT模式则通过数据快照和全局锁来实现最终一致性,虽然数据不是实时一致的,但在最终状态上保持一致,这种模型在某些场景下可以接受,并且减少了锁的使用,提高了性能。

3. 侵入性降低

  • 代码侵入性:XA模式通常需要业务代码显式地参与事务管理,如调用XA接口等。而AT模式则是一种无侵入的分布式事务解决方案,用户只需关注自己的业务SQL,Seata框架会自动处理事务的二阶段提交和回滚操作,降低了对业务代码的侵入性。

4. 依赖性和灵活性

  • 数据库依赖性:XA模式高度依赖关系型数据库来实现事务的强一致性。而AT模式虽然也依赖数据库,但更多地是通过Seata框架的数据快照和全局锁机制来实现最终一致性,因此对数据库的依赖性和要求相对较低。
  • 灵活性:AT模式提供了更高的灵活性,它支持多种数据库类型(如MySQL、Oracle、PostgreSQL和TiDB等),并且可以根据业务需求进行灵活配置和调整。

3.2、Saga 模式

Saga 模式是一种长事务解决方案,其核心思想是将一个业务流程中的长事务,拆分成多个本地短事务。业务流程中的每个参与者都提交真实的提交给本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿前面已经成功的参于者。

Sage 由一系列 sub-transaction T i 组成,每个 T i 都有对应的补偿动作 C i ,补偿动作用于撤销 T i 造成的数据变更结果。每一个 T i 操作都真实的影响数据库。

Sage 模式的两种执行方式

  • T1、T2、T3、 ... 、T i :这种方式表示所有事务都正常执行。
  • T1、T2、 ... 、T j 、C j 、... 、C2、C1(其中 0 < j < i):这种方式表示执行到 T j 事务时出现异常,通过补充操作撤销之前所有成功的 sub-transaction.

Sage 提供了两种补偿恢复方式

  • ① 向后恢复:如果任一子事务执行失败,则把之前执行的结果逐一撤销。
  • ② 向前恢复:该恢复方式不进行补偿,而是对失败的事务进行重试,其比较适合于事务必须要执行成功的场景。

Saga 的优劣势

  • 和XA 和 TCC 相比,Saga 的一阶段直接提交本地事务,没有锁等待,性能比较高;在事件驱动的模式下,短事务可以异步执行;补偿机制的实现比较简单。
  • Sage 的缺点是并不提供原子性和隔离性支持,隔离性的影响比较大。比如 业务中赠送了一张优惠券,若用户将优惠券使用了,且事务如果出现异常要回滚就会出现问题。

.

相关推荐
java_heartLake1 个月前
中间件之Seata
分布式·中间件·分布式事务
IT云清1 个月前
Apache Seata Raft模式配置中心
java·分布式·apache·seata·分布式事务
Dylanioucn1 个月前
【分布式微服务云原生】掌握Java分布式事务:2PC、3PC、TCC与Seata全解析
分布式·微服务·云原生·分布式事务
灰色孤星A2 个月前
分布式事务学习笔记(四)微服务实现Stata AT模式、Stata Saga模式介绍
微服务·seata·分布式事务·at模式·saga模式·微服务实现seata
灰色孤星A2 个月前
分布式事务学习笔记(二)Seata架构、TC服务器部署、微服务集成Seata
分布式·微服务·架构·seata·分布式事务·tc服务器·微服务集成seata
长安初雪3 个月前
微服务集成 Seata
微服务·云原生·架构·seata·分布式事务
丁总学Java3 个月前
使用kafka改造分布式事务
分布式·kafka·分布式事务
JinYD20183 个月前
分布式事务和一致性
分布式·分布式事务·一致性
tmax52HZ4 个月前
分布式事务-使用队列实现最终一致性
消息队列·分布式事务·cap·最终一致性·下单扣减库存
普通程序员A4 个月前
springCloud组件专题(五) --- seata
后端·spring·spring cloud·面试·seata·分布式事务