Seata TCC模式 #

一、TCC模式概述 #

1.1 什么是TCC模式 #

TCC模式是一种补偿型分布式事务解决方案,分为Try、Confirm、Cancel三个阶段。

text
┌─────────────────────────────────────────────────────────────┐
│                    TCC模式流程                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Try阶段:资源预留                                          │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│   │ 冻结库存    │  │ 冻结余额    │  │ 创建订单    │        │
│   └─────────────┘  └─────────────┘  └─────────────┘        │
│                                                             │
│   Confirm阶段:确认提交                                      │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│   │ 扣减库存    │  │ 扣减余额    │  │ 订单成功    │        │
│   └─────────────┘  └─────────────┘  └─────────────┘        │
│                                                             │
│   Cancel阶段:取消回滚                                       │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│   │ 释放库存    │  │ 释放余额    │  │ 取消订单    │        │
│   └─────────────┘  └─────────────┘  └─────────────┘        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 TCC vs AT #

特性 TCC AT
侵入性
性能
灵活性
开发成本

二、实现TCC #

2.1 定义接口 #

java
@LocalTCC
public interface InventoryService {

    @TwoPhaseBusinessAction(name = "prepareDeduct", commitMethod = "commit", rollbackMethod = "rollback")
    boolean prepareDeduct(@BusinessActionContextParameter(paramName = "productId") Long productId,
                          @BusinessActionContextParameter(paramName = "count") Integer count);

    boolean commit(BusinessActionContext context);

    boolean rollback(BusinessActionContext context);
}

2.2 实现接口 #

java
@Service
public class InventoryServiceImpl implements InventoryService {

    @Override
    public boolean prepareDeduct(Long productId, Integer count) {
        return inventoryMapper.freeze(productId, count) > 0;
    }

    @Override
    public boolean commit(BusinessActionContext context) {
        Long productId = context.getActionContext("productId", Long.class);
        Integer count = context.getActionContext("count", Integer.class);
        return inventoryMapper.deduct(productId, count) > 0;
    }

    @Override
    public boolean rollback(BusinessActionContext context) {
        Long productId = context.getActionContext("productId", Long.class);
        Integer count = context.getActionContext("count", Integer.class);
        return inventoryMapper.unfreeze(productId, count) > 0;
    }
}

三、问题处理 #

3.1 空回滚 #

java
@Override
public boolean rollback(BusinessActionContext context) {
    String xid = context.getXid();
    if (!tryExecuted(xid)) {
        return true;
    }
    return inventoryMapper.unfreeze(productId, count) > 0;
}

3.2 悬挂 #

java
@Override
public boolean prepareDeduct(Long productId, Integer count) {
    String xid = RootContext.getXID();
    if (rollbackExecuted(xid)) {
        return false;
    }
    return inventoryMapper.freeze(productId, count) > 0;
}

四、总结 #

要点 说明
Try 资源预留
Confirm 确认提交
Cancel 取消回滚
空回滚 Try未执行但收到Cancel
悬挂 Cancel先于Try执行

接下来让我们学习 安全认证

最后更新:2026-03-28