- 一般在
微服务
开发中,一个接口中涉及多服务调用,涉及在不同数据库的数据修改时,为了保证数据一致性等,就需要引入分布式事务。- 在
单应用
引入本地事务@Transactional(rollbackFor = Throwable.class)
,就可以。- 而分布式事务可以用
spring cloud alibaba - seata
框架实现,在部署好nacos、seata客户端后,在接口声明@GlobalTransactional
,就可以实现。
Seata介绍:是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
常见分布式事务解决方案:
- seata阿里分布式事务框架
- 消息队列,可靠消息-》文章
- Saga
- XA
事务模式介绍:
- AT 模式:是一种无侵入分布式事务解决方案。
– 1阶段: Seata会拦截业务sql,解析sql语义找到业务sql要更新的数据,在数据更新前
,保存更新前快照before image;然后执行业务sql更新数据;在数据更新后
,将其保持成 after images,更新后快照,生成行锁。
– 2阶段:如果接口正常执行
未出现异常,因为业务sql在一阶段已提交,接口正常执行后删除快照数据和行锁,完全数据清理; 接口执行出现异常时
,就会回滚数据,先执行脏写校检
,对比当前数据库业务数据,与after image,如果一致则可以还原业务数据,出现脏写则需要人工处理;无脏写时,则通过before image 生成逆向sql还原数据。- TCC 模式:侵入性较强,自己实现相关事务控制逻辑,在整个过程基本没有锁,性能更强。
– 事务发起方在一阶段执行Try方式,在二阶段提交执行confirm,回滚执行cancel。
版本对应 –
下载对应版本运行体,以及运行配置以及表
如1.4.2 版本
基本配置https://github.com/seata/seata/tree/1.4.2
运行jar https://github.com/seata/seata/tags
前置环境:只需配置一次
- 修改 seata-server-1.4.2\conf ,file.conf,选择对应存储模式,默认file单机模式
这里记录高可用db模式,修改file.conf 文件,切换db模式,并修改数据链接信息。
- 修改 register.conf ,配置nacos连接信息。(事务参与者,需要与 seata通信);确保nacos正常启动后,修改源码中script资源目录下,\config-center\config.txt 修改注册信息,配置存储模式,数据库连接信息,事务分组信息,之后运行注册脚本
nacos-config.sh
,将信息注册到nacos。
- 导入资源目录中数据库信息,创建数据库seata;执行 script\server\db\mysql.sql 文件
- 运行 seata-server.bat
集群启动:
在服务参与者对应库中,添加 undo_log 表; 保持执行前后的源数据,script\client\at\db\mysql.sql
代码整合
父项目依赖:
<dependencyManagement>
<dependencies>
<!--spring boot 公共版本定义-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 公共版本定义 通过dependencies完成继承-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
服务端依赖:
<!-- 客户端调用-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
服务参与者yml配置:
spring:
application:
name: stock-service
cloud:
nacos:
config:
group: DEFAULT_GROUP
server-addr: 127.0.0.1:8848 #nacos服务地址
file-extension: yaml #配置文件类型
#事务分组
alibaba:
seata:
tx-service-group: my_test_tx_group
#seata 配置
seata:
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server
username: nacos
password: nacos
group: SEATA_GROUP
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
group: SEATA_GROUP
接口处,或service中 @GlobalTransactional
@GlobalTransactional
@RequestMapping("/add")
public String add(){
Order order = new Order(9,20,0);
orderMapper.insert(order);
String reduct = stockService.reduct(9);
int i=1/0;
return "ok"+reduct;
}
前置环境配置有点烦琐,但只需配置一次,后续执行声明注解就可以实现分布式事务。
TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
流程分析,AT模式总结:
1 TC会生成一个XID作为该全局事务的编号。XID,会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起。
2. 在进入接口方法时,生成一个XID;将事务参与者,注册为全局事务的一个事务分支。每一个事务都是通过全局事务的XID来进行隔离,有多个分布式事务 @GlobalTransactional 就会有多个XID。多个XID来串联起这些事务参与者。
global_table
,存储全局事务信息。
branch_table
分支事务信息。存储事务参与者
lock_table
锁表信息,目的:分支事务之间的隔离
undo_log
回滚快照数据