Java TCC 分布式事务全面解析
一、TCC 核心原理与特性
1. 三阶段事务模型
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. 电商下单流程
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);
}
}
十、最佳实践总结
-
服务设计原则:
- 每个业务操作必须实现Try/Confirm/Cancel接口
- 保持操作幂等性
- 合理设置事务超时时间
-
事务日志管理:
- 使用独立数据库存储事务状态
- 定期清理已完成事务日志
- 实现事务恢复补偿机制
-
性能优化点:
- 异步执行Confirm/Cancel操作
- 批量处理事务日志写入
- 使用本地事务表提升性能
-
监控指标:
-
容灾方案:
- 事务协调器集群部署
- 多副本日志存储
- 跨机房容灾部署
-
调试技巧:
- 使用全局XID追踪事务链路
- 记录详细事务操作日志
- 实现事务可视化监控
完整实现示例参考:java-tcc-framework(示例仓库)
通过合理设计事务边界和补偿机制,TCC能够在分布式系统中实现高一致性事务处理,适用于需要强一致性保证的金融交易、订单处理等关键业务场景。开发过程中需重点关注事务的幂等性、悬挂问题处理以及可靠的事务恢复机制。
更多资源:
http://sj.ysok.net/jydoraemon 访问码:JYAM