Seata 分布式事务 XA 模式
Seata 是一个开源的分布式事务解决方案,提供了高性能和易用的分布式事务服务。Seata 支持多种事务模式,其中 XA 模式是 Seata 支持的一种强一致性分布式事务模式。
在 Seata 的 XA 模式中,事务管理器(Transaction Manager, TM)协调多个资源管理器(Resource Manager, RM)来确保事务的原子性。XA 模式基于两阶段提交(2PC)协议,分为准备阶段和提交/回滚阶段。
下面是一个 Seata XA 模式的入门级介绍和示例:
### 1. 理解 Seata XA 模式
- **XA 协议**:XA 是由 X/Open 组织提出的分布式事务规范。它定义了一个全局的事务管理器(TM)和多个本地资源管理器(RM)之间的接口。TM 负责协调所有参与者(RM)以完成分布式事务。
- **两阶段提交(2PC)**:
- **准备阶段(Phase 1)**:TM 向所有参与者发送准备请求,参与者执行事务操作(但不提交),并将操作结果(成功/失败)报告给 TM。
- **提交阶段(Phase 2)**:如果所有参与者都准备成功,TM 发送提交请求,参与者提交事务;如果有任何一个参与者准备失败,TM 发送回滚请求,参与者回滚事务。
- **Seata XA 模式**:Seata 实现了 XA 协议,将 Seata 服务器(TC,Transaction Coordinator)作为事务管理器,而将各个微服务中的数据库作为资源管理器。Seata 的 XA 模式对业务代码侵入性低,只需要在方法上添加 `@GlobalTransactional` 注解即可开启全局事务。
### 2. 使用 Seata XA 模式的步骤
#### 步骤 1: 引入依赖
在 Spring Boot 项目中,引入 Seata 的依赖。以 Maven 为例:
```xml
<!-- seata starter -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>最新版本</version>
</dependency>
<!-- 数据库驱动(如MySQL) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据源(如Druid) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
```
#### 步骤 2: 配置 Seata
在 `application.yml` 中配置 Seata:
```yaml
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: my_tx_group # 事务组名称,需要与Seata Server配置一致
service:
vgroup-mapping:
my_tx_group: default # 映射到Seata Server的集群名称
grouplist:
default: 127.0.0.1:8091 # Seata Server地址
registry:
type: file # 注册中心类型,这里使用文件,生产环境建议使用nacos等
config:
type: file # 配置中心类型,这里使用文件
data-source-proxy-mode: XA # 指定代理模式为XA
```
#### 步骤 3: 数据库配置
确保每个微服务的数据源配置正确,并且 Seata 可以代理数据源。
#### 步骤 4: 使用全局事务注解
在业务方法上添加 `@GlobalTransactional` 注解,开启全局事务:
```java
@Service
public class BusinessService {
@Autowired
private OrderService orderService;
@Autowired
private StorageService storageService;
@GlobalTransactional // 开启全局事务
public void purchase(String userId, String commodityCode, int orderCount) {
storageService.deduct(commodityCode, orderCount);
orderService.create(userId, commodityCode, orderCount);
// 如果发生异常,会回滚事务
}
}
```
#### 步骤 5: 启动 Seata Server
下载 Seata Server 并启动。下载地址:https://github.com/seata/seata/releases
启动命令(以单机模式为例):
```bash
sh seata-server.sh -p 8091 -h 127.0.0.1 -m file
```
### 3. XA 模式的特点
- **优点**:
- 强一致性:遵循两阶段提交协议,保证数据的强一致性。
- 简单易用:对业务代码侵入低,只需要添加一个注解。
- 支持多语言:Seata 支持 Java、Go、Python 等多种语言。
- **缺点**:
- 性能:两阶段提交协议在提交阶段需要等待所有参与者的响应,性能相对较差。
- 锁资源时间长:在准备阶段就会锁定资源,直到提交或回滚,因此资源锁定时间较长。
### 4. 示例项目结构
一个典型的分布式事务场景包括多个微服务,例如:
- **订单服务(Order Service)**:创建订单
- **库存服务(Storage Service)**:扣减库存
在 `purchase` 方法中,先调用库存服务扣减库存,再调用订单服务创建订单。如果任何一个服务失败,整个事务将回滚。
### 5. 注意事项
- **数据库支持**:确保使用的数据库支持 XA 事务(如 MySQL、Oracle、PostgreSQL 等)。
- **Seata Server 高可用**:生产环境中,Seata Server 需要配置为高可用模式,可以使用 Nacos 等作为注册中心和配置中心。
- **避免长事务**:由于 XA 模式会长时间锁定资源,应避免在事务中进行耗时操作。
通过以上步骤,你就可以在项目中快速集成 Seata 的 XA 模式来实现分布式事务了。
Seata 分布式事务入门:XA 模式详解
什么是分布式事务?
在微服务架构中,当一个业务操作需要跨多个服务/数据库时,需要保证这些操作要么全部成功,要么全部失败,这就是分布式事务。分布式事务是构建可靠微服务系统的关键挑战之一。
Seata 简介
Seata 是阿里巴巴开源的分布式事务解决方案,提供高性能和易用的分布式事务服务。Seata 支持四种模式:
-
XA 模式:强一致性模式
-
AT 模式:无侵入的分布式事务解决方案
-
TCC 模式:高性能分布式事务模式
-
SAGA 模式:长事务解决方案
XA 模式详解
XA 协议基础
XA 协议由 X/Open 组织提出,定义了分布式事务的规范:
-
事务管理器 (TM):协调全局事务
-
资源管理器 (RM):管理本地资源(如数据库)
-
两阶段提交 (2PC):
-
准备阶段:所有参与者准备提交
-
提交阶段:所有参与者实际提交
-
Seata XA 模式架构
复制
下载
[Client] │▼ [Seata TM] ←→ [Seata TC (Transaction Coordinator)]│▼ [RM1] [RM2] [RM3]
-
TM:定义事务边界,开启/提交/回滚全局事务
-
TC:事务协调者,维护全局事务状态
-
RM:管理分支事务,向TC注册分支事务状态
XA 模式特点
-
强一致性:保证数据的强一致性
-
简单易用:对业务代码侵入小
-
支持广泛:主流数据库都支持XA协议
-
锁时间长:资源锁定时间较长
实战:Seata XA 模式示例
环境准备
-
启动 Seata Server:
bash
复制
下载
sh seata-server.sh -p 8091 -m file
-
添加依赖:
xml
复制
下载
运行
<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.1</version> </dependency>
配置 Seata
yaml
复制
下载
# application.yml seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: my_tx_groupservice:vgroup-mapping:my_tx_group: defaultgrouplist:default: 127.0.0.1:8091data-source-proxy-mode: XA
业务服务示例
订单服务
java
复制
下载
@Service public class OrderService {@Autowiredprivate OrderMapper orderMapper;@GlobalTransactionalpublic void createOrder(Order order) {orderMapper.insert(order);// 调用库存服务扣减库存inventoryFeignClient.deduct(order.getProductId(), order.getCount());} }
库存服务
java
复制
下载
@Service public class InventoryService {@Autowiredprivate InventoryMapper inventoryMapper;public void deduct(String productId, int count) {inventoryMapper.deduct(productId, count);} }
XA 模式执行流程
-
TM 开启全局事务
-
向 TC 注册全局事务
-
生成全局唯一的 XID
-
-
RM 执行分支事务
-
执行业务 SQL
-
向 TC 注册分支事务
-
报告分支事务状态
-
-
TM 提交/回滚事务
-
向 TC 发起全局提交/回滚
-
TC 通知所有 RM 提交/回滚分支事务
-
事务控制台
Seata 提供了事务监控控制台:
复制
下载
http://localhost:7091
XA 模式 vs AT 模式
特性 | XA 模式 | AT 模式 |
---|---|---|
一致性 | 强一致性 | 最终一致性 |
锁范围 | 全局锁 | 行锁 |
锁持有时间 | 整个事务过程 | 业务SQL执行时间 |
回滚 | 基于数据库回滚 | 基于回滚日志 |
性能 | 较低 | 较高 |
侵入性 | 低(标准XA接口) | 低(自动代理) |
适用场景 | 短事务、强一致性要求 | 高并发、最终一致性可接受 |
最佳实践
-
事务范围控制
-
尽量保持事务短小
-
避免在事务中包含远程调用和复杂计算
-
-
异常处理
java
复制
下载
@GlobalTransactional public void businessMethod() {try {// 业务逻辑} catch (Exception e) {// 手动回滚TransactionalExecutor.rollback();throw e;} }
-
超时设置
yaml
复制
下载
seata:client:tm:commit-retry-count: 5rollback-retry-count: 5
-
XA 模式优化
-
使用数据库连接池
-
调整数据库XA配置
-
避免长事务
-
常见问题排查
-
XAER_RMERR: XA resource manager error
-
检查数据库XA支持是否开启
-
验证数据库连接配置
-
-
Global lock conflict
-
检查是否有并发事务操作相同数据
-
优化事务粒度
-
-
TransactionException: Timeout
-
增加事务超时时间
-
优化慢SQL
-
总结
Seata XA 模式提供了一种强一致性的分布式事务解决方案:
-
基于标准的 XA 协议实现
-
对业务代码侵入小
-
适合需要强一致性的场景
-
简单易用,与数据库原生集成
对于需要强一致性保证且事务时间较短的场景,XA 模式是一个可靠的选择。在实际应用中,需要根据业务需求权衡一致性和性能要求,选择合适的分布式事务模式。