在分布式系统中,如果一个业务需要多个服务合作完成,而且每一个服务都有事务, 多个事务必须同时成功或失败,这样的事务就是分布式事务。其中的每个服务的事务就是一个分支事务。 整个业务称为全局事务。
初识Seata
Seata是2019年1月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式 事务服务,为用户打造一-站式的分布式解决方案。
官网地址: http://seata.iol, 其中的文档、播客中提供了大量的使用说明、源码分析。
分布式事务解决思路
解决分布式事务,各个子事务之间必须能感知到彼此的事务状态,才能保证状态一致。
Seata架构
在Seata的事务管理中有三个重要的角色:
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
部署TC服务
准备数据库表
Seata支持多种存储模式,但考虑到持久化的需要,我们一般选择基于数据库存储。执行《seata-tc.sql》
,导入数据库表:
准备配置文件
我们将整个seata文件夹拷贝到虚拟机的/root
目录:
Docker部署
docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.21.129 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network hm-net \
-d \
seataio/seata-server:1.5.2
微服务集成Seata
首先,要引入Seata依赖:
<!--统一配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
改造配置
首先在nacos上添加一个共享的seata配置,命名为shared-seata.yaml
:
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
type: nacos # 注册中心类型 nacos
nacos:
server-addr: 192.168.21.129:8848 # nacos地址
namespace: "" # namespace,默认为空
group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
application: seata-server # seata服务名称
username: nacos
password: nacos
tx-service-group: hmall # 事务组名称
service:
vgroup-mapping: # 事务组与tc集群的映射关系
hmall: "default"
然后,在application.yml中添加配置,让微服务找到TC服务地址
XA模式
XA规范是x/Open组织定义的分布式事务处理(DTP,Distributed Transaction Processing) 标准,XA规范描述了全局的TM与局部的RM之间的接口,几乎所有主流的关系型数据库都对XA规范提供了支持。Seata的XA模式如下:
一阶段:
①RM注册分支事务到TC
②RM执行分支业务sq|但不提交
③RM报告执行状态到TC
二阶段:
TC检测各分支事务执行状态
a.如果都成功,通知所有RM提交事务
b.如果有失败,通知所有RM回滚事务
RM接收TC指令,提交或回滚事务
优点
●事务的强一致性,满足ACID原则。
●常用数据库都支持,实现简单,并且没有代码侵入
缺点
●因为-阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
●依赖关系型数据库实现事务
实现
Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:
1.修改application.yml文件 ( 每个参与事务的微服务),开启XA模式:
2.给发起全 局事务的入口方法添加@GlobalTransactional注解,本例中是OrderServicelmpl中的create方法:
AT模式
Seata主推的是AT模式,AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。
阶段一RM的工作:
●注册分支事务
●记录undo-log ( 数据快照)
●执行业务sql并提交
●报告事务状态
阶段二提交时RM的工作:
- 删除undo-log即可
阶段二回滚时RM的工作:
- 根据undo-log恢复数据到更新前
实现
首先添加一张表到数据库中
注意:是每个数据库增加这张表
然后修改yml文件,将事务模式改为AT模式:
AT模式与XA模式最大的区别
●XA模式一阶段不提交事务,锁定资源; AT模式一阶段直接提交,不锁定资源。
●XA模式依赖数据库机制实现回滚; AT模式利用数据快照实现数据回滚。
●XA模式强一 致; AT模式最终一致