ata TCC模式通过业务层定义Try/Confirm/Cancel接口实现分布式事务,适用于高并发、跨数据库/服务场景,需手动处理幂等、空回滚和悬挂问题。
一、Seata TCC模式核心原理
1. 三阶段设计
- Try:资源检查与预留(如冻结库存、锁定账户余额)。
- Confirm:确认执行业务操作(释放预留资源,如扣减冻结库存),需保证幂等性。
- Cancel:回滚预留资源(如解冻库存),需保证幂等性。
2. 与AT模式对比
| 维度 | TCC模式 | AT模式 |
|---|---|---|
| 侵入性 | 高(需手动实现三阶段接口) | 低(自动生成回滚日志) |
| 适用场景 | 跨数据库/中间件、高并发 | 单一关系型数据库 |
| 性能 | 高(无全局锁) | 中(需全局锁和undo_log) |
---
二、Seata TCC落地步骤
1. 环境准备 (智优达参考)
- 依赖引入(Spring Boot项目):
xml
<dependency> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> <version>1.6.1</version> </dependency> - 配置Seata(application.yml):
yaml
seata: enabled: true tx-service-group: my_tx_group service: vgroup-mapping: my_tx_group: default grouplist: default: 127.0.0.1:8091 # Seata Server地址
2. TCC接口定义与实现
示例:库存服务
java
// TCC接口 public interface InventoryTccAction { // Try阶段:冻结库存 @TwoPhaseBusinessAction(name = "deductInventory", commitMethod = "commit", rollbackMethod = "rollback") boolean tryDeduct(BusinessActionContext context, @BusinessActionContextParameter(paramName = "productId") Long productId, @BusinessActionContextParameter(paramName = "count") Integer count); // Confirm阶段:确认扣减 boolean commit(BusinessActionContext context); // Cancel阶段:回滚冻结 boolean rollback(BusinessActionContext context); } // 实现类 @Service public class InventoryTccActionImpl implements InventoryTccAction { @Autowired private InventoryMapper inventoryMapper; @Override @Transactional public boolean tryDeduct(BusinessActionContext context, Long productId, Integer count) { // 1. 检查库存是否充足 // 2. 冻结库存(update inventory set frozen = frozen + count where product_id = ?) return inventoryMapper.freezeStock(productId, count) > 0; } @Override public boolean commit(BusinessActionContext context) { Long productId = Long.valueOf(context.getActionContext("productId").toString()); Integer count = Integer.valueOf(context.getActionContext("count").toString()); // 扣减冻结库存(update inventory set stock = stock - count, frozen = frozen - count where product_id = ?) return inventoryMapper.commitDeduct(productId, count) > 0; } @Override public boolean rollback(BusinessActionContext context) { Long productId = Long.valueOf(context.getActionContext("productId").toString()); Integer count = Integer.valueOf(context.getActionContext("count").toString()); // 解冻库存(update inventory set frozen = frozen - count where product_id = ?) return inventoryMapper.rollbackFreeze(productId, count) > 0; } }
3. 发起全局事务
java
@Service public class OrderService { @Autowired private InventoryTccAction inventoryTccAction; @GlobalTransactional // Seata全局事务注解 public void createOrder(Long productId, Integer count) { // 调用TCC接口的Try方法 boolean success = inventoryTccAction.tryDeduct(null, productId, count); if (!success) { throw new RuntimeException("库存不足"); } // 创建订单(本地事务) orderMapper.insert(new Order(productId, count)); } }
---
三、关键问题处理
1. 幂等性
- 方案:基于
xid+branchId(Seata事务ID)记录操作状态,避免重复执行。sql
CREATE TABLE tcc_fence_log ( xid VARCHAR(128) NOT NULL, branch_id BIGINT NOT NULL, status TINYINT NOT NULL, -- 1: tried, 2: committed, 3: rollbacked PRIMARY KEY (xid, branch_id) );
2. 空回滚
- 原因:Try阶段未执行,TC触发Cancel。
- 处理:在Cancel方法中检查Try是否执行(通过tcc_fence_log),未执行则直接返回成功。
3. 悬挂
-
原因:Cancel先于Try执行(网络延迟)。
-
处理:Try方法执行前检查Cancel是否已执行,是则拒绝执行。

1000

被折叠的 条评论
为什么被折叠?



