掘金 后端 ( ) • 2022-11-30 13:46

欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈

0. 环境

  • nacos版本:1.4.1
  • Spring Cloud : 2020.0.2
  • Spring Boot :2.4.4
  • Spring Cloud alibaba: 2.2.5.RELEASE
  • Spring Cloud openFeign 2.2.2.RELEASE

测试代码:https://github.com/hsfxuebao/springcloud-source-study

1. Seata 概述

1.1 分布式事务简介

对于分布式事务,通俗地说就是,一次操作由若干分支操作组成,这些分支操作分属不同应用,分布在不同服务器上。分布式事务需要保证这些分支操作要么全部成功,要么全部失败。 分布式事务与普通事务一样,都是为了保证操作结果的一致性。

1.2 Seata 简介

以下是来自于 Seata 官网的介绍:

Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务

在 Seata 开源之前, Seata 对应的内部版本在阿里经济体内部一直扮演着分布式一致性中间件的角色,帮助经济体平稳的度过历年的双 11,对各 BU 业务进行了有力的支撑。经过多年沉淀与积累,商业化产品先后在阿里云、金融云进行售卖。 2019.1 为了打造更加完善的技术生态和普惠技术成果, Seata 正式宣布对外开源,未来 Seata 将以社区共建的形式帮助其技术更加可靠与完备。

Seata 官网: http://seata.io/zh-cn/

1.3 Seata 术语

Seata 中有三个常用术语: TCTMRM

1.3.1 TC

Transaction Coordinator事务协调者。维护全局和分支事务的状态(记录全局事务与分支事 务的执行结果),驱动全局事务提交或回滚。

1.3.2 TM

Transaction Manager,事务管理器。定义全局事务的范围:开始全局事务、提交或回滚全局 事务。 TM 就是全局事务的发起者。

1.3.3 RM

Resource Manager,资源管理器。管理分支事务处理的资源,与 TC 交谈(通信) 以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

常见的 DBMS 在分布式系统中都是以 RM 的角色出现的。

2. 分布式事务模式

Seata 提供了 ATTCCSAGAXA 事务模式。

2.1 业务场景模拟

为了方便以下分布式模式的理解,下面以特定的场景来分析。

某企业完成了一次采购,需要修改 DRP 系统中的数据。在系统中提交了本次采购清单后,本次提交操作实际修改了分属两个 DBMS采购表 purchase库存表 stock。而这两个表的修改是需要满足一致性的,即本次操作实际是由应用程序发起了一个分布式的事务。系统架构图如下:

image.png

2.2 XA 模式

XA(Unix Transaction) 是一种分布式事务解决方案,一种分布式事务处理模式,是基于 XA协议的。XA协议由Tuxedo(Transaction for Unix has been Extended for Distributed Operation,分布式操作扩展之后的 Unix 事务系统)首先提出的,并交给 X/Open 组织,作为资源管理器 与事务管理器的接口标准。

XA 模式架构图:

image.png

XA 模式是一个典型的 2PC,其执行原理如下:

  1. TM 向 TC 发起指令,开启一个全局事务。

  2. 根据业务要求,各个 RM 会逐个向 TC 注册分支事务,然后 TC 会逐个向 RM 发出预执行 指令(第一阶段提交)。

  3. 各个 RM 在接收到指令后会在进行本地事务预执行。

  4. RM 将预执行结果 Report 给 TC。当然,这个结果可能是成功,也可能是失败。

  5. TC 在接收到各个 RM 的 Report 后会将汇总结果上报给 TM,根据汇总结果 TM 会向 TC 发出确认指令。

    • 若所有结果都是成功响应,则向 TC 发送 Global Commit 指令。
    • 只要有结果是失败响应,则向 TC 发送 Global Rollback 指令。
  6. TC 在接收到指令后再次向 RM 发送确认指令(第二阶段提交)。 该模式存在的问题:

    • 在各个 RM 执行第一阶段的本地事务预执行时,为了保证将来能够回滚,会在本地记录 回滚日志。当所有 RM 第一阶段全部执行成功后, TM 会通过 TC 向所有 RM 下达 Commit 指令(二阶段提交指令)。此时回滚日志就没有用了,就可以清理掉了。 XA 模式的问题 就是,这些回滚日志需要通过手工进行清理,无法自动清理。
    • 在多线程环境下对同一个 RM 中的数据进行修改,存在 ABA 问题。

2.3 AT 模式

AT, Automatic Transaction。 AT 模式是 Seata 默认的分布式事务模型,是由 XA 模式演变 而来的,通过全局锁对 XA 模式中的问题进行了改进,并实现了回滚日志的自动清理

AT 模式存在的问题: prepare 阶段与 commit/rollback 阶段,及回滚日志的清理过程,完 全实现了“自动化”,无法实现“定制化”过程。

2.4 TCC 模式

image.png

TCCTry Confirm/Cancel,同样也是 2PC 的,其与 AT 的重要区别是,支持将自定义的分 支事务纳入到全局事务管理中,即可以实现定制化的日志清理与回滚过程。当然,该模式对业务逻辑的侵入性是较大的。

2.5 2PC 缺陷(补充)

2PC 最大的特点就是简单:原理简单,实现简单。但却存在先天缺陷: 同步阻塞、 中心 化问题、数据不一致、太过保守等。不过,若实现方案设计的较好,这些缺陷是可以弱化的。

同步阻塞

在一个分布式事务执行期间,所有 RM 预执行 prepare 完自己的分支事务后就会处于阻 塞状态,等待 TC 再次下发指令(二阶段指令)。而 TC 只有在收到所有 RM 的结果后才会再 次发出指令。 而这期间那些已经完成分支事务的 RM 中的资源将一直处于锁定状态。

中心化问题

TC 一旦出现问题,整个系统就会崩溃。

数据不一致

在 TC 发送“最终确认”指令(二阶段提交)时,若由于网络等原因,只有部分 RM 收 到指令,或 TC 没有发送完毕最终确认指令就宕机了。此时,收到指令的 RM 会执行确认指 令,而未收到的则无法完成事务。若若自行解锁,就可能会导致 RM 中的数据的不一致。

太过保守

任何一个 RM 在 Prepare 阶段执行失败,都将引发分布式事务的全局性失败。

2.6 Saga 模式

对于架构复杂,且业务流程较多较长的系统,一般不适合使用 2PC 的分布式模式。因为这种系统一般无法提供 TMTCRM 三种接口。此时,我们可以尝试着选择 Saga 模式。

Saga 模式是 1987 年由普林斯顿大学的 Hector Garcia-Molina 和 Kenneth Salem 共同提出 的。该模式不同于前面的模式,它不是 2PC 的,其是一种长事务解决方案

image.png

其应用场景是:在无法提供 TCTMRM 接口的情况下,对于一个流程很长的复杂业务,其会包含很多的子流程(事务)。每个子流程都让它们真实提交它们真正的执行结果。

只有当前子流程执行成功后才能执行下一个子流程。若整个流程中所有子流程全部执行成功, 则整个业务流程成功;只要有一个子流程执行失败,则可采用两种补偿方式:

  • 向后恢复: 对于其前面所有成功的子流程,其执行结果全部撤销
  • 向前恢复: 重试失败的子流程直到其成功。当然这个前提是要确保每个分支事务都能够成功。

Saga 中没有类似于 TC 这样的全局性管理者,所以管理工作都是由各个本地事务自行完成的。 Sage 模式的所有分支事务的执行是串行的,同步的,而 2PC 的则是并行的,异步的。

参考文章

Seata官网文档
springcloud-source-study学习github地址
微服务入门到入土