【手把手】教你玩转SpringCloud Alibaba之Seata

1、事务的概念

分布式事务理论

事务的四大特性:
A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失 败的情况;
C(Consistency):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100元, 转账前和转账后的数据是正确状态这叫一致性,如果出现张三转出100元,李四账户没有增加100元这就出现了数 据错误,就没有达到一致性;
I(Isolation):隔离性,数据库中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事 不能看到其他事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题;
D(Durability):持久性,事务完成之后,该事务对数据的更改会被持久化到数据库,且不会被回滚;

本地事务:同一数据库和服务器,称为本地事务。在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务,由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。

分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操 作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如:用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。

通过以上的图中可以看出,其实只要涉及到操作多个数据源,就可能会产生事务问题,当然在实际开发中要尽量避免这种问题的出现,当然如果避免不了,就需要进行解决。在微服务系统架构中,目前比较好、比较常用的解决方案就是Seata。

CAP定律

随着互联化的蔓延,各种项目都逐渐向分布式服务做转换。如今微服务已经普遍存在,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生。 分布式事务被称为世界性的难题,目前分布式事务存在两大理论依据:CAP定律 和 BASE理论。

CAP定律指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

- 一致性(C)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本);

- 可用性(A)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性);

- 分区容错性(P)
以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择;

CAP三者是无法同时存在的

1、当库存服务减库存以后,那么需要将数据同步到其他的服务上,这是为了保证数据一致性C,但是网络是不可靠的,所以我们系统就需要保证分区容错性P,也就是我们必须容忍网络所带来的的一些问题,此时如果我们想保证C那么就需要舍弃A,也就是说我们在保证C的情况下,就必须舍弃A,也就是CP无法保证高可用;

2、如果为了保证A,高可用的情况下,也就是必须在限定时间内给出响应,同样由于网络不可靠P,订单服务就有可能无法拿到新的数据,但是也要给用户作出响应,那么也就无法保证C一致性。所以AP是无法保证强一致性的;

3、如果我们想保证CA,也就是高可用和一致性,也就是必须保证网络良好才能实现,那么也就是说我们需要将库存、订单、用户放到一起,但是这种情况也就丧失了P这个保证,这个时候系统也就不是分布式系统了;

4、总结:在分布式系统中,P是必然的存在的,所以我们只能在C和A之间进行取舍,在这种条件下就诞生了BASE理论;

BASE理论

BASE是Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

- 基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。注意,这绝不等价于系统不可用。比如:
(1)响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒
(2)系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面

- 软状态
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时

- 最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。

基本可用:保证核心服务是可以使用的,其他的服务可以适当的降低响应时间,甚至是服务降级

软状态:存在中间状态,不影响整体系统使用,数据同步存在延时

最终一致性:再过了流量高峰期以后,经过一段时间的同步,保持各服务数据的一致

分布式事务解决方案

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,P是指准备阶段,C是指提交阶段。
1、准备阶段(prepare phase)
2、提交阶段(commit phase)

比如说相亲对象两个人去吃饭,店老板要求,先付钱在吃饭,这是男女双方提出了AA,也就是说只有男女双方都付钱,才能落座吃饭,但是只要两个人中有一个不统一付款就不能落座吃饭。
- 准备阶段:老板要求男方付款,男方付款。老板要求女方付款,女方付款;
- 提交阶段:老板出餐,两人纷纷落座;

其实这就形成了一个事务,如果男女双方有一个人拒绝付款,那么老板就不会出餐,并且会把已收取的钱原路退回。整个事务过程是由事务管理器和参与者组成的,店老板就是事务管管理器,男女双发就是参与者,事务管理器决策整个分布式事务在计算机中关系数据库支持的两阶段提交协议:
- 准备阶段(prepare phase):事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交;(Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)
- 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的资源;

2、什么是Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

在微服务系统中,对应业务被对应的拆分成独立模块,在官方提供的架构图中,可以看出当前是三个服务:
- 仓储服务:对给定的商品进行增删操作记录数量
- 订单服务:根据采购者的需求创建订单
- 账户服务:从用户账户中扣除余额、积分等

在这套架构中,用户下单购买商品的业务,就需要三个服务来完成,每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题就没办法保证,Seata就是来进行解决这种问题的解决方案。

要了解Seata,首先我们要了解一下Seata的几个关键的概念:
- TC (Transaction Coordinator) - 事务协调者。维护全局和分支事务的状态,驱动全局事务提交或回滚;
- TM (Transaction Manager) - 事务管理器(发起者,同时也是RM的一种)。定义全局事务的范围:开始全局事务、提交或回滚全局事务;
- RM (Resource Manager) - 资源管理器(每个参与事务的微服务)。管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚;

Seata的事务模式

Seata 定义了全局事务的框架。全局事务 定义为若干 分支事务 的整体协调:
1、TM 向 TC 请求发起(Begin)、提交(Commit)、回滚(Rollback)全局事务;
2、TM 把代表全局事务的 XID 绑定到分支事务上;
3、RM 向 TC 注册,把分支事务关联到 XID 代表的全局事务中;
4、RM 把分支事务的执行结果上报给 TC(可选);
5、TC 发送分支提交(Branch Commit)或分支回滚(Branch Rollback)命令给 RM;

Seata 的 全局事务 处理过程,分为两个阶段:
- 执行阶段 :执行分支事务,并保证执行结果满足是可回滚的(Rollbackable)和持久化的(Durable);
- 完成阶段: 根据 执行阶段 结果形成的决议,应用通过 TM 发出的全局提交或回滚的请求给 TC,TC 命令 RM 驱动 分支事务 进行 Commit 或 Rollback;

Seata 的所谓事务模式是指:运行在 Seata 全局事务框架下的 分支事务 的行为模式。准确地讲,应该叫作 分支事务模式。不同的 事务模式 区别在于 分支事务 使用不同的方式达到全局事务两个阶段的目标。即:
- 执行阶段 :如何执行并 保证 执行结果满足是可回滚的(Rollbackable)和持久化的(Durable);
- 完成阶段: 收到 TC 的命令后,如何做到分支的提交或回滚;

3、Seata的下载与安装

和其它的SpringCloud组件一样,Seata项目也在Git上进行开源:https://github.com/seata/seata/releases,这里使用1.4.2这个版本作为演示的版本。

将下载后的Seata压缩包解压后,进入conf目录下,编辑registry.conf配置文件,将注册中心和配置中心都改为注册到Nacos中:

编辑file.conf配置文件,将Seata的存储方式改为db,并配置数据库链接信息:

注意:如果数据库链接版本较新的话,那么driverClassName的值应是com.mysql.cj.jdbc.Driver

确保Nacos服务启动成功之后,就可以直接启动Seata服务:

可以看到Seata服务已经启动成功,并在Nacos中注册成功:

4、Seata Server (TC) 环境搭建

Server端存储模式(store.mode)支持三种:
1、file:单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,因为是在内存中直接进行操作,所以这也是性能最高的模式(默认);
2、db:高可用模式,全局事务会话信息通过DB共享,相对性能差一些;
3、redis:1.3及以上版本支持,性能较高,但存在事务信息丢失风险,需要配合实际场景使用;

另外在file.conf配置文件中,注意其中涉及到了三个表,分别是global_table,branch_table,lock_table分别是全局事务会话表,分支事务会话表,锁数据表:

Seata并不会自动创建这三张表,这三张表需要手动去创建,官方提供的建表语句链接:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql

Seata支持注册服务到Nacos,以及支持Seata所有配置放到Nacos配置中心,在Nacos中统一维护,高可用模式下就需要配合Nacos来完成:

再前面已经编辑了registry.conf配置文件,将注册中心和配置中心都改为注册到Nacos中:

注意:确保client与server的注册处于同一个namespace和group,不然会找不到服务。

配置文件内容参考:https://github.com/seata/seata/tree/develop/script/config-center 的config.txt,并按需修改保存

将这个配置文件下载到本地后,主要就是将其中的模式改为 db 高可用模式,以及配置数据库链接信息。配置完成之后,将此配置文件放到Seata的主目录下:

配置改完以后,需要把这些配置一个个的加入到Nacos配置中,所以需要一个脚本来进行执行。官方已经提供好了,地址为:https://github.com/seata/seata/blob/develop/script/config-center/nacos/nacos-config.sh

在Seata的主目录下文件夹中新建一个脚本文件nacos-config.sh,然后把脚本内容复制进去:

注意:原脚本中找寻config.txt文件是去别的路劲中找寻,需要改成在当前目录下找寻:

修改保存后,使用Git Bash来执行这个脚本:

登录Nacos查看Seata的相关配置:

5、Seata AT模式

AT 模式是一种无侵入的分布式事务解决方案,在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

两阶段提交协议的演变:
一阶段:
    业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源;
二阶段:
    - 提交异步化,非常快速地完成;
    - 回滚通过一阶段的回滚日志进行反向补偿;

在一阶段中,Seata会拦截“业务SQL”,首先解析SQL语义,找到要更新的业务数据,在数据被更新前,保存下来“undo”,然后执行“业务SQL”更新数据,更新之后再次保存数据“redo”,最后生成行锁,这些操作都在本地数据库事务内完成,这样保证了一阶段的原子性。

相对一阶段,二阶段比较简单,负责整体的回滚和提交,如果之前的一阶段中有本地事务没有通过,那么就执行全局回滚,否在执行全局提交,回滚用到的就是一阶段记录的“undo Log”,通过回滚记录生成反向更新SQL并执行,以完成分支的回滚。当然事务完成后会释放所有资源和删除所有日志。

具体到落地执行就是:

执行阶段:
    - 可回滚:根据 SQL 解析结果,记录回滚日志
    - 持久化:回滚日志和业务 SQL 在同一个本地事务中提交到数据库
完成阶段:
    - 分支提交:异步删除回滚日志记录
    - 分支回滚:依据回滚日志进行反向补偿更新

既然是分布式服务,那么自然需要至少两个服务才能演示对应的效果。创建两个服务,分别是订单服务:order-8801、库存服务:stock-8802

order-8801对应的数据库表为:

stock-8802对应的数据库表为:

order-8801引入相关依赖及yml文件配置:

stock-8802引入相关依赖及yml文件配置:

order-8801相关业务代码:

stock-8802相关业务代码: 

启动order-8801和stock-8802,访问 http://localhost:8801/order/create

可以看到正常情况下,库存-1和订单+1的数据都更改完成:

现在在order-8801中手动搞一个异常,模拟多服务之间的运行出错:

再次访问 http://localhost:8801/order/create,就会发现执行错误,但是看数据库中的数据,库存已经减了,但是订单没有生成:

为了解决分布式服务之间的事务问题,这时候就需要Seata上场了。在order-8801和stock-8802之间引入seata的相关依赖:

在order-8801和stock-8802的yml配置文件上对seata进行配置:

这个yml配置中的值需要和之前上传到Nacos中的配置值要对应起来,否则在Nacos中读取不到相关的配置使用的时候就会报错。

在数据库中创建 undo_log 表,用于数据的回滚:

在order-8801的Controller上添加全局事务注解,因为order服务在整个事务的过程中充当事务发起者的角色:

启动Seata服务,切记切记,此时启动Seata服务的时候一定要指定监听注册的端口号:

这可是一个大坑,如果不加参数 -p 8091,虽然可以启动,但是8801和8802服务将无法注册到Seata中,会报[0101 can not connect to 192.168.31.134:8091 cause:can not register RM.....]这样的错误。

启动order-8801和stock-8802两个的服务,可以看到在Seata中注册成功:

再次访问 http://localhost:8801/order/create,就会发现运行时报 / by zero 的异常,并且从输出的日志可以看到,全局事务已经被Seata回滚完成:

在异常处打个断点,当order-8801本地的数据入库之后,会在Seata的undo_log中插入一条记录:

里面详细记录了全局事务执行前后数据库中关联的数据:

{"@class":"io.seata.rm.datasource.undo.BranchUndoLog","xid":"192.168.31.134:8091:5179470428400054273","branchId":5179470428400054275,"sqlUndoLogs":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.undo.SQLUndoLog","sqlType":"UPDATE","tableName":"stock","beforeImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"stock","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"id","keyType":"PRIMARY_KEY","type":-5,"value":["java.lang.Long",1]},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"count","keyType":"NULL","type":-5,"value":["java.lang.Long",13]}]]}]]},"afterImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"stock","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"id","keyType":"PRIMARY_KEY","type":-5,"value":["java.lang.Long",1]},{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"count","keyType":"NULL","type":-5,"value":["java.lang.Long",12]}]]}]]}}]]}

当执行出现异常的时候,就会按照记录下的日志进行数据的回滚,回滚执行完之后,会把undo_log中的数据清除掉。

6、Seata XA模式

什么是XA协议

XA 模式是Seata 1.2.0版本重磅发布新的事务模式,实现对 XA 协议的支持。XA 规范早在上世纪 90 年代初就被提出,用以解决分布式事务处理这个领域的问题。注意:不存在某一种分布式事务机制可以完美适应所有场景,满足所有需求。现在,无论 AT 模式、TCC 模式还是 Saga 模式,这些模式的提出,本质上都源自 XA 规范对某些场景需求的无法满足。

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准。XA 规范 描述了全局的事务管理器与局部的资源管理器之间的接口。 XA规范 的目的是允许的多个资源(如数据库,应用服务器,消息队列等)在同一事务中访问,这样可以使 ACID 属性跨越应用程序而保持有效。XA 规范 使用两阶段提交(2PC,Two-Phase Commit)来保证所有资源同时提交或回滚任何特定的事务。XA 规范 在上世纪 90 年代初就被提出。目前,几乎所有主流的数据库都对 XA 规范 提供了支持。

DTP模型定义如下角色:
- AP:即应用程序,可以理解为使用DTP分布式事务的程序;
- RM:资源管理器,可以理解为事务的参与者,一般情况下是指一个数据库的实例(MySql),通过资源管理器对该数据库进行控制,资源管理器控制着分支事务;
- TM:事务管理器,负责协调和管理事务,事务管理器控制着全局事务,管理实务生命周期,并协调各个RM;

全局事务是指分布式事务处理环境中,需要操作多个数据库共同完成一个工作,这个工作即是一个全局事务。DTP模式定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现的2PC又称为XA方案。

1、应用程序(AP)持有订单库和商品库两个数据源;
2、应用程序(AP)通过TM通知订单库(RM)和商品库(RM),来创建订单和减库存,RM此时未提交事务,此时商品和订单资源锁定;
3、TM收到执行回复,只要有一方失败则分别向其他RM发送回滚事务,回滚完毕,资源锁释放;
4、TM收到执行回复,全部成功,此时向所有的RM发起提交事务,提交完毕,资源锁释放;

XA协议的痛点

基于此模式下,如果一个参与全局事务的资源 “失联” 了(收不到分支事务结束的命令),那么它锁定的数据,将一直被锁定,甚至可能因此产生死锁。这是 XA 协议的核心痛点,也是 Seata 引入 XA 模式要重点解决的问题。

Seata的XA模式

在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。

执行阶段:
    - 可回滚:业务 SQL 操作放在 XA 分支中进行,由资源对 XA 协议的支持来保证 可回滚;
    - 持久化:XA 分支完成后,执行 XA prepare,同样,由资源对 XA 协议的支持来保证持久化(即,之后任何意外都不会造成无法回滚的情况);
完成阶段:
    - 分支提交:执行 XA 分支的 commit;
    - 分支回滚:执行 XA 分支的 rollback;

为什么要在Seata中支持XA

本质上,Seata 已经支持的 3 大事务模式:AT、TCC、Saga 都是 补偿型 的。补偿型 事务处理机制构建在 事务资源 之上(要么在中间件层面,要么在应用层面),事务资源 本身对分布式事务是无感知的。事务资源 对分布式事务的无感知存在一个根本性的问题:无法做到真正的 全局一致性。比如,一条库存记录,处在 补偿型 事务处理过程中,由 100 扣减为 50。此时,仓库管理员连接数据库,查询统计库存,就看到当前的 50。之后,事务因为异外回滚,库存会被补偿回滚为 100。显然,仓库管理员查询统计到的 50 就是 脏数据,所以补偿型事务是存在中间状态的(中途可能读到脏数据)。

与 补偿型 不同,XA 协议 要求 事务资源 本身提供对规范和协议的支持。因为 事务资源 感知并参与分布式事务处理过程,所以 事务资源(如数据库)可以保障从任意视角对数据的访问有效隔离,满足全局数据一致性。比如,刚才提到的库存更新场景,XA 事务处理过程中,中间状态数据库存 50 由数据库本身保证,是不会仓库管理员的查询统计看到的。除了 全局一致性 这个根本性的价值外,支持 XA 还有如下几个方面的好处:
1、业务无侵入:和 AT 一样,XA 模式将是业务无侵入的,不给应用设计和开发带来额外负担;
2、数据库的支持广泛:XA 协议被主流关系型数据库广泛支持,不需要额外的适配即可使用;
3、多语言支持容易:因为不涉及 SQL 解析,XA 模式对 Seata 的 RM 的要求比较少;
4、传统基于 XA 应用的迁移:传统的,基于 XA 协议的应用,迁移到 Seata 平台,使用 XA 模式将更平滑;

在当前的技术发展阶段,不存一个分布式事务处理机制可以完美满足所有场景的需求。一致性、可靠性、易用性、性能等诸多方面的系统设计约束,需要用不同的事务处理机制去满足。Seata 项目最核心的价值在于:构建一个全面解决分布式事务问题的 标准化 平台。基于 Seata,上层应用架构可以根据实际场景的需求,灵活选择合适的分布式事务解决方案。XA 模式的加入,补齐了 Seata 在 全局一致性 场景下的缺口,形成 AT、TCC、Saga、XA 四大 事务模式 的版图,基本可以满足所有场景的分布式事务处理诉求。

7、Seata TCC模式

什么是TCC

TCC 是分布式事务中的二阶段提交协议,它的全称为 Try-Confirm-Cancel,即资源预留(Try)、确认操作(Confirm)、取消操作(Cancel),具体含义如下:
Try:对业务资源的检查并预留;
Confirm:对业务处理进行提交,即 commit 操作,只要 Try 成功,那么该步骤一定成功;
Cancel:对业务处理进行取消,即回滚操作,该步骤回对 Try 预留的资源进行释放;

TCC 是一种侵入式的分布式事务解决方案,以上三个操作都需要业务系统自行实现,对业务系统有着非常大的入侵性,设计相对复杂,但优点是 TCC 完全不依赖数据库,能够实现跨数据库、跨应用资源管理,对这些不同数据访问通过侵入式的编码方式实现一个原子操作,更好地解决了在各种复杂业务场景下的分布式事务问题。

业务应用相当于TM(事务管理器),开始/提交/回滚全局事务;

事务协调器相当于TC(事务协调者),维护全局或分支事务状态,驱动全局事务提交或回滚;

服务A/B相当于RM(资源管理器),向TC注册分支事务,驱动分支事务提交或回滚;

TCC 模式和AT 模式的区别

AT 模式基于支持本地 ACID 事务的关系型数据库:
- 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录;
- 二阶段 commit 行为:马上成功结束,自动异步批量清理回滚日志;
- 二阶段 rollback 行为:通过回滚日志,自动生成补偿操作,完成数据回滚;

相应的,TCC 模式,不依赖于底层数据资源的事务支持:
- 一阶段 prepare 行为:调用自定义的 prepare 逻辑;
- 二阶段 commit 行为:调用自定义的 commit 逻辑;
- 二阶段 rollback 行为:调用自定义的 rollback 逻辑;

所谓 TCC 模式,是指支持把自定义的分支事务纳入到全局事务的管理中。侵入性比较强,并且需要自己实现相关事务控制逻辑,在整个过程基本没有锁,性能较强。

8、Seata Saga模式

什么是Saga

Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务(执行处理时候出错了,给一个修复的机会)都由业务开发实现。Saga 模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga 模式是一种长事务解决方案。

为什么需要Saga

之前在Seata分布式三种操作模型中所使用的的微服务全部可以根据开发者的需求进行修改,但是在一些特殊环境下,比如老系统,封闭的系统(无法修改,同时没有任何分布式事务引入),那么AT、XA、TCC模型将全部不能使用,为了解决这样的问题,才引用了Saga模型。比如:事务参与者可能是其他公司的服务或者是遗留系统,无法改造,可以使用Saga模式。

Saga模式是Seata提供的长事务解决方案,提供了异构系统的事务统一处理模型。在Saga模式中,所有的子业务都不在直接参与整体事务的处理(只负责本地事务的处理),而是全部交由了最终调用端来负责实现,而在进行总业务逻辑处理时,在某一个子业务出现问题时,则自动补偿全面已经成功的其它参与者,这样一阶段的正向服务调用和二阶段的服务补偿处理全部由总业务开发实现。

Saga状态机

目前Seata提供的Saga模式只能通过状态机引擎来实现,需要开发者手工的进行Saga业务流程绘制,并且将其转换为Json配置文件,而后在程序运行时,将依据子配置文件实现业务处理以及服务补偿处理,而要想进行Saga状态图的绘制,一般需要通过Saga状态机来实现:
- 通过状态图来定义服务调用的流程并生成json定义文件;
- 状态图中一个节点可以调用一个服务,节点可以配置它的补偿节点;
- 状态图 json 由状态机引擎驱动执行,当出现异常时状态引擎反向执行已成功节点对应的补偿节点将事务回滚;
- 可以实现服务编排需求,支持单项选择、并发、子流程、参数转换、参数映射、服务执行状态判断、异常捕获等功能;

猜你喜欢

转载自blog.csdn.net/FeenixOne/article/details/127913485