在 Alibaba Spring Cloud Seata 中,Resource Manager (RM) 是三大核心组件之一。它主要负责管理分支事务中的资源(如数据库、文件等),并与 Transaction Coordinator (TC) 协作完成分支事务的注册、提交和回滚。RM 是分布式事务实际操作的执行者,保证本地事务与全局事务的协调一致。
1. RM 的核心功能
-
分支事务的注册:
- 在本地事务执行前,RM 向 TC 注册分支事务。
- RM 将分支事务绑定到全局事务(通过
XID
关联)。
-
分支事务的执行:
- RM 在本地事务中执行具体的业务逻辑(如数据库操作)。
-
分支事务状态的报告:
- RM 在本地事务完成后,向 TC 汇报分支事务的执行状态(成功或失败)。
-
事务提交或回滚:
- 根据 TC 的指令,RM 提交或回滚分支事务。
- 在 AT 模式 中,RM 会通过 Undo Log(回滚日志)恢复数据状态。
2. RM 的工作原理
RM 是嵌入在业务服务中的组件,用于处理资源操作的事务管理。以下是 RM 的主要工作流程:
2.1 分支事务注册
- 在分支事务执行之前,RM 向 TC 发起注册请求。
- TC 返回分支事务 ID,并将其记录在全局事务中。
2.2 分支事务执行
- RM 执行具体的资源操作,例如:
- 数据库的插入、更新操作。
- 消息队列的发送。
- 在 AT 模式 中,RM 还会记录 Undo Log(回滚日志)。
2.3 状态报告
- 分支事务执行完成后,RM 向 TC 报告执行结果(成功或失败)。
2.4 提交或回滚
- 如果 TC 决定提交事务,RM 提交本地事务。
- 如果 TC 决定回滚事务,RM 根据 Undo Log 恢复本地事务的初始状态。
3. RM 在不同模式下的表现
3.1 AT 模式
- 在 AT 模式中,RM 使用 JDBC 拦截器记录 Undo Log,管理数据库事务。
- Undo Log 记录每次更新前的数据快照,用于回滚时恢复原始状态。
执行过程:
- 本地事务执行时,生成 Undo Log。
- TC 指定提交时,清除 Undo Log。
- TC 指定回滚时,读取 Undo Log 恢复原始数据。
3.2 TCC 模式
- 在 TCC 模式中,RM 手动实现分支事务的三阶段逻辑:
- Try:预留资源。
- Confirm:正式提交资源。
- Cancel:释放预留资源。
执行过程:
Try
阶段执行预留逻辑,例如冻结库存或资金。- TC 指定提交时,调用
Confirm
方法。 - TC 指定回滚时,调用
Cancel
方法。
3.3 SAGA 模式
- RM 执行业务的前向操作和补偿操作。
- 每个分支事务需要实现补偿逻辑。
4. RM 的实现与使用
4.1 配置 RM
RM 是嵌入在业务服务中的组件,通过 Spring Boot 配置实现。
引入依赖
在业务服务的 pom.xml
中添加 Seata 的依赖:
xml
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
配置数据源代理
在 application.yml
中配置 Seata 的数据源代理:
yaml
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
seata:
enabled: true
tx-service-group: my_tx_group
Seata 会自动代理数据源,拦截事务操作并记录 Undo Log。
4.2 使用 RM 管理分支事务
以下示例展示了一个扣减库存的分支事务:
java
@Service
public class InventoryService {
@Autowired
private InventoryRepository inventoryRepository;
// 分支事务:扣减库存
public void deductStock(Long productId, int quantity) {
Inventory inventory = inventoryRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("商品不存在"));
if (inventory.getAvailableStock() < quantity) {
throw new RuntimeException("库存不足");
}
// 扣减库存
inventory.setAvailableStock(inventory.getAvailableStock() - quantity);
inventoryRepository.save(inventory);
}
}
4.3 AT 模式下的 Undo Log
Undo Log 表结构
在数据库中创建 Undo Log 表,用于记录回滚日志:
sql
CREATE TABLE undo_log (
id BIGINT AUTO_INCREMENT,
branch_id BIGINT NOT NULL,
xid VARCHAR(128) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info LONGBLOB NOT NULL,
log_status INT NOT NULL,
log_created TIMESTAMP NOT NULL,
log_modified TIMESTAMP NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (xid, branch_id)
);
Undo Log 的生成与使用
- 生成: 在每次本地事务执行时,Seata 自动生成 Undo Log。
- 使用: 在回滚时,Seata 读取 Undo Log 恢复数据。
5. RM 的配置项
以下是 RM 的常用配置项:
seata.client.rm.async.commit.buffer.limit
- 异步提交的缓冲区大小。
- 默认值:10000。
seata.client.rm.lock.retry.interval
- 获取分布式锁时的重试间隔(毫秒)。
- 默认值:10。
seata.client.rm.lock.retry.times
- 获取分布式锁的最大重试次数。
- 默认值:30。
6. RM 的运行与调试
检查事务锁
在分布式事务执行时,RM 会为操作的资源添加分布式锁,锁信息存储在 lock_table
中。
锁表结构
sql
CREATE TABLE lock_table (
row_key VARCHAR(128) NOT NULL,
xid VARCHAR(128) NOT NULL,
transaction_id BIGINT,
branch_id BIGINT,
resource_id VARCHAR(256),
gmt_create TIMESTAMP,
gmt_modified TIMESTAMP,
PRIMARY KEY (row_key)
);
检查 Undo Log
当事务需要回滚时,RM 会读取 undo_log
表并恢复数据。
7. RM 的性能优化与注意事项
-
Undo Log 清理:
- 定期清理历史 Undo Log,避免表数据膨胀。
- Seata 提供了自动清理工具。
-
分布式锁性能:
- 优化
lock_table
的索引,提升锁的获取效率。 - 在高并发场景下,尽量缩小事务粒度,减少锁冲突。
- 优化
-
事务粒度控制:
- 避免在一个事务中操作过多的资源,防止事务冲突。
-
事务超时配置:
- 配置合理的事务超时时间,避免长时间锁定资源。
8. 总结
Resource Manager (RM) 是 Seata 框架中管理分支事务的关键组件,负责资源的实际操作和事务的提交与回滚。在开发中:
- RM 的行为由具体的事务模型(AT、TCC 等)决定。
- 在 AT 模式下,RM 依赖 Undo Log 来支持事务的回滚。