分布式事务:Seata与TCC模式落地实践

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是否已执行,是则拒绝执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值