在现代软件开发中,随着微服务架构的普及,应用被分解为多个独立部署的服务。虽然这种方式提高了系统的灵活性和可扩展性,但也带来了新的挑战,尤其是在数据一致性方面。本文将介绍一个强大的开源解决方案------Seata,它旨在帮助开发者轻松应对微服务架构中的分布式事务问题。
目录
[XA 模式](#XA 模式)
[AT 模式](#AT 模式)
[TCC 模式](#TCC 模式)
[Saga 模式](#Saga 模式)
分布式事务介绍
分布式事务是指跨越多个计算机节点或数据库的事务处理过程。在传统的单体应用中,ACID(原子性、一致性、隔离性、持久性)特性相对容易实现。然而,在微服务环境中,由于涉及到不同服务之间的交互,确保这些特性的难度大大增加。例如,在订单处理过程中,既要更新库存系统也要更新支付信息,任何一步失败都可能导致数据不一致。
Seata的核心概念与架构
Seata 是一个开源的分布式事务解决方案,旨在为微服务架构中的分布式事务提供高可用、高性能的支持。它由阿里巴巴集团主导开发,并于2019年开源。
Seata的核心组件
- Transaction Coordinator (TC):事务协调器,维护全局事务和分支事务的状态,驱动全局事务的提交或回滚。
- Transaction Manager (TM):事务管理器,定义全局事务的边界,负责开启全局事务、提交或回滚全局事务。
- Resource Manager (RM):资源管理器,管理分支事务处理的数据的资源,与TC通信以注册分支事务并报告状态。
如下图所示:

Seata的工作模式
XA 模式
XA模式遵循XA规范,支持两阶段提交协议(2PC),适用于对一致性要求高的场景。XA模式需要数据库的支持,比如MySQL、Oracle等都提供了对XA的支持。(性能较低,强一致性)
AT 模式
这是一种无侵入式的分布式事务解决方案,适用于基于Spring Cloud、Dubbo等微服务框架的应用。在AT模式下,Seata自动拦截SQL操作,记录数据快照,并通过比较前后快照来决定如何提交或回滚事务。(推荐使用,Seata默认实现)
流程图如下:

TCC 模式
TCC是一种补偿型事务模式,要求业务逻辑必须分为三个阶段:尝试(Try)、确认(Confirm)和取消(Cancel)。尝试阶段完成所有业务检查,预留必要的业务资源;确认阶段执行实际的业务操作;取消阶段释放预留的业务资源。(对事务过程中的每一个步骤都有精确的控制)
Saga 模式
Saga模式适合长事务场景,将一个长事务拆分成多个本地事务序列,每个本地事务都有相应的补偿操作用于撤销之前的操作。如果前面的事务失败,则执行后续的补偿操作来恢复系统状态。(包含多个本地事务且能够接受最终一致性)
Seata的部署及应用
部署Seata服务
Seata支持多种存储模式,但考虑到持久化的需要,我们一般选择基于数据库存储。

准备一个seata目录,其中包含了seata运行时所需要的配置文件:

将整个seata文件夹拷贝到虚拟机的**/root**目录

在虚拟机的**/root
**目录执行下面的命令:
java
docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.150.101 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network hm-net \
-d \
seataio/seata-server:1.5.2
通过以下命令进行观察Seata日志:
java
docker logs -f seata
登录你自己的虚拟机地址:7099,如下页面即部署成功

微服务集成Seata
引入依赖
java
<!--统一配置管理-->
<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
**:
java
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
type: nacos # 注册中心类型 nacos
nacos:
server-addr: 192.168.150.101: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"
在配置文件中配置**shared-seata.yaml:(下方的共享seata配置)
**
java
spring:
application:
name: cart-service # 服务名称
profiles:
active: dev
cloud:
nacos:
server-addr: 192.168.12.132::8848 # nacos地址
config:
file-extension: yaml # 文件后缀名
shared-configs: # 共享配置
- dataId: shared-jdbc.yaml # 共享mybatis配置
- dataId: shared-log.yaml # 共享日志配置
- dataId: shared-swagger.yaml # 共享日志配置
- dataId: shared-seata.yaml # 共享seata配置
在运行项目后,进行测试:
故意制造分布式事务不一致的情况:下单商品后,修改库存,进入支付业务中,观察控制台。
我们以AT模式为例,结果如下:

直接回滚到支付的状态,购物车也没有清除,实现了事务一致。