分布式事务算法——TCC 分布式事务全面解析

在这里插入图片描述

Java TCC 分布式事务全面解析

一、TCC 核心原理与特性
1. 三阶段事务模型
应用 事务协调器 服务A 服务B 开启全局事务 Try Try成功 Try Try成功 Confirm Confirm 事务提交成功 应用 事务协调器 服务A 服务B
2. 核心特性对比
特性 TCC 2PC Saga
事务锁 业务资源预留 数据库行锁 无锁
一致性 强一致性 强一致性 最终一致性
实现复杂度
适用场景 短事务、高一致性要求 数据库层事务 长事务、最终一致
性能影响 较高
二、Java 实现核心组件
1. 事务协调器设计
public class TransactionCoordinator {
    
    
    // 事务日志存储
    private TransactionLogStore logStore;
    
    // 开启事务
    public String begin() {
    
    
        String xid = generateXID();
        logStore.logBegin(xid);
        return xid;
    }
    
    // 提交事务
    public void commit(String xid) {
    
    
        List<Participant> participants = logStore.getParticipants(xid);
        executePhase(xid, participants, Phase.CONFIRM);
        logStore.logCompleted(xid);
    }
    
    // 回滚事务
    public void rollback(String xid) {
    
    
        List<Participant> participants = logStore.getParticipants(xid);
        executePhase(xid, participants, Phase.CANCEL);
        logStore.logCompleted(xid);
    }
}
2. 参与者注解定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TccAction {
    
    
    String confirmMethod();  // Confirm方法名
    String cancelMethod();   // Cancel方法名
    int timeout() default 60; // 超时时间(秒)
}
三、业务服务实现示例
1. 库存服务实现
public class InventoryService {
    
    
    private Map<Long, Integer> inventory = new ConcurrentHashMap<>();
    private Map<String, InventoryLock> locks = new ConcurrentHashMap<>();

    @TccAction(confirmMethod = "confirmDeduct", 
              cancelMethod = "cancelDeduct")
    public boolean deduct(String xid, Long itemId, int count) {
    
    
        int available = inventory.getOrDefault(itemId, 0);
        if (available < count) {
    
    
            return false;
        }
        locks.put(xid, new InventoryLock(itemId, count));
        return true;
    }

    public boolean confirmDeduct(String xid) {
    
    
        InventoryLock lock = locks.remove(xid);
        inventory.compute(lock.itemId, (k, v) -> v - lock.count);
        return true;
    }

    public boolean cancelDeduct(String xid) {
    
    
        locks.remove(xid);
        return true;
    }
}
2. 订单服务实现
public class OrderService {
    
    
    private Map<String, Order> orders = new ConcurrentHashMap<>();

    @TccAction(confirmMethod = "confirmCreate", 
              cancelMethod = "cancelCreate")
    public boolean createOrder(String xid, Order order) {
    
    
        order.setStatus(OrderStatus.TRYING);
        orders.put(xid, order);
        return true;
    }

    public boolean confirmCreate(String xid) {
    
    
        Order order = orders.get(xid);
        order.setStatus(OrderStatus.CONFIRMED);
        return true;
    }

    public boolean cancelCreate(String xid) {
    
    
        orders.remove(xid);
        return true;
    }
}
四、事务拦截器实现
1. AOP 切面处理
@Aspect
@Component
public class TccTransactionAspect {
    
    
    @Autowired
    private TransactionCoordinator coordinator;
    
    @Around("@annotation(tccAction)")
    public Object aroundTccMethod(ProceedingJoinPoint joinPoint, TccAction tccAction) throws Throwable {
    
    
        String xid = TransactionContext.getXID();
        
        // 注册参与者
        Participant participant = new Participant(
            joinPoint.getTarget().getClass(),
            tccAction.confirmMethod(),
            tccAction.cancelMethod(),
            joinPoint.getArgs()
        );
        coordinator.registerParticipant(xid, participant);
        
        try {
    
    
            Object result = joinPoint.proceed();
            if (!(Boolean)result) {
    
    
                coordinator.rollback(xid);
            }
            return result;
        } catch (Exception e) {
    
    
            coordinator.rollback(xid);
            throw e;
        }
    }
}
2. 事务上下文管理
public class TransactionContext {
    
    
    private static ThreadLocal<String> xidHolder = new ThreadLocal<>();
    
    public static String getXID() {
    
    
        return xidHolder.get();
    }
    
    public static void bind(String xid) {
    
    
        xidHolder.set(xid);
    }
    
    public static void unbind() {
    
    
        xidHolder.remove();
    }
}
五、事务恢复机制
1. 事务日志存储设计
public interface TransactionLogStore {
    
    
    void logBegin(String xid);
    void logParticipant(String xid, Participant participant);
    void logCompleted(String xid);
    List<String> findTimeoutXids(int timeout);
    List<Participant> getParticipants(String xid);
}

// 基于数据库的实现
public class JdbcTransactionLogStore implements TransactionLogStore {
    
    
    // 使用事务日志表存储状态
    // CREATE TABLE tcc_log (
    //   xid VARCHAR(64) PRIMARY KEY,
    //   status VARCHAR(20),
    //   create_time TIMESTAMP,
    //   update_time TIMESTAMP
    // )
}
2. 事务恢复服务
public class TransactionRecoveryService {
    
    
    @Scheduled(fixedRate = 60000) // 每分钟执行
    public void recoverTimeoutTransactions() {
    
    
        List<String> timeoutXids = logStore.findTimeoutXids(60);
        timeoutXids.forEach(xid -> {
    
    
            List<Participant> participants = logStore.getParticipants(xid);
            if (allParticipantsTried(xid)) {
    
    
                coordinator.commit(xid);
            } else {
    
    
                coordinator.rollback(xid);
            }
        });
    }
}
六、生产级优化策略
1. 幂等性保证
public class IdempotentValidator {
    
    
    private Set<String> processedXids = Collections.newSetFromMap(
        new ConcurrentHashMap<>());
    
    public boolean checkAndRecord(String xid) {
    
    
        return processedXids.add(xid);
    }
    
    @Scheduled(fixedRate = 3600000)
    public void cleanExpiredXids() {
    
    
        // 清理24小时前的记录
    }
}
2. 异步Confirm/Cancel
public class AsyncTransactionExecutor {
    
    
    private ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public void asyncConfirm(String xid, List<Participant> participants) {
    
    
        executor.submit(() -> {
    
    
            participants.parallelStream().forEach(p -> {
    
    
                try {
    
    
                    p.confirm();
                } catch (Exception e) {
    
    
                    // 重试逻辑
                    retryConfirm(p, 3);
                }
            });
        });
    }
    
    private void retryConfirm(Participant p, int maxRetries) {
    
    
        // 指数退避重试
    }
}
七、异常处理机制
1. 悬挂问题处理
public class HangPreventer {
    
    
    public void checkHanging(String xid) {
    
    
        if (logStore.getStatus(xid) == Status.TRYING 
            && System.currentTimeMillis() - createTime > timeout) {
    
    
            coordinator.rollback(xid);
        }
    }
}
2. 重试策略配置
tcc:
  retry:
    max-attempts: 3
    backoff:
      initial-interval: 1000ms
      multiplier: 2
八、性能优化方案
1. 批量日志写入
public class BatchLogWriter {
    
    
    private List<LogEntry> buffer = new ArrayList<>();
    
    @Scheduled(fixedDelay = 1000)
    public void flushBuffer() {
    
    
        List<LogEntry> copy;
        synchronized (buffer) {
    
    
            copy = new ArrayList<>(buffer);
            buffer.clear();
        }
        jdbcTemplate.batchUpdate(copy);
    }
    
    public void addLog(LogEntry entry) {
    
    
        synchronized (buffer) {
    
    
            buffer.add(entry);
        }
    }
}
2. 本地事务表优化
-- 创建本地事务表
CREATE TABLE local_tcc_log (
  xid VARCHAR(64) PRIMARY KEY,
  status VARCHAR(20),
  create_time TIMESTAMP(3),
  INDEX idx_status_create (status, create_time)
) ENGINE=InnoDB;
九、典型应用场景
1. 电商下单流程
成功
成功
全部成功
失败
失败
失败
用户下单
库存服务-Try
优惠券服务-Try
订单服务-Try
Confirm阶段
扣减库存
核销优惠券
创建正式订单
Cancel阶段
2. 跨行转账场景
public class TransferService {
    
    
    @Transactional
    public void transfer(String xid, String from, String to, BigDecimal amount) {
    
    
        // Try阶段
        accountService.freeze(from, amount);
        accountService.freeze(to, amount.negate());
        
        // Confirm阶段
        accountService.confirmDebit(from, amount);
        accountService.confirmCredit(to, amount);
    }
}
十、最佳实践总结
  1. 服务设计原则

    • 每个业务操作必须实现Try/Confirm/Cancel接口
    • 保持操作幂等性
    • 合理设置事务超时时间
  2. 事务日志管理

    • 使用独立数据库存储事务状态
    • 定期清理已完成事务日志
    • 实现事务恢复补偿机制
  3. 性能优化点

    • 异步执行Confirm/Cancel操作
    • 批量处理事务日志写入
    • 使用本地事务表提升性能
  4. 监控指标

    85% 12% 3% TCC事务状态分布 成功 失败 进行中
  5. 容灾方案

    • 事务协调器集群部署
    • 多副本日志存储
    • 跨机房容灾部署
  6. 调试技巧

    • 使用全局XID追踪事务链路
    • 记录详细事务操作日志
    • 实现事务可视化监控

完整实现示例参考:java-tcc-framework(示例仓库)

通过合理设计事务边界和补偿机制,TCC能够在分布式系统中实现高一致性事务处理,适用于需要强一致性保证的金融交易、订单处理等关键业务场景。开发过程中需重点关注事务的幂等性、悬挂问题处理以及可靠的事务恢复机制。

更多资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

本文发表于【纪元A梦】,关注我,获取更多免费实用教程/资源!