(一) 混合事务架构设计(Saga + TCC)
1. 架构设计原则
- 业务分层:
- 核心业务(资金/库存)使用TCC模式保证强一致性
- 非核心业务(订单/物流)使用Saga模式提高吞吐量
- 事务边界清晰:
- 明确划分需要强一致性的操作和允许最终一致性的操作
- 补偿机制独立:
- TCC和Saga的补偿操作分开设计,互不干扰
- 监控统一:
- 建立统一的监控系统跟踪两种事务的执行状态
2. 架构分层设计
文章中的mermaid 经常报错 直接生成图片 贴出来
3. 关键组件设计
(1)业务编排层(事务协调器)
// 混合事务协调器
public class HybridTransactionManager {
private TccTransactionManager tccManager;
private SagaTransactionManager sagaManager;
public void executeHybridTransaction(HybridTransaction tx) {
// 1. 执行TCC阶段
tccManager.executeTry(tx.getTccOperations());
// 2. 执行Saga阶段
sagaManager.execute(tx.getSagaOperations());
// 3. 确认TCC阶段(如果Saga成功)
if (sagaManager.isCompleted(tx.getId())) {
tccManager.executeConfirm(tx.getTccOperations());
} else {
// Saga失败则补偿TCC
tccManager.executeCancel(tx.getTccOperations());
}
}
}
(2)TCC服务设计
// TCC服务接口
public interface TccService {
void tryOperation(TccOperation op); // 预留资源
void confirmOperation(TccOperation op); // 确认操作
void cancelOperation(TccOperation op); // 取消操作
}
// 典型实现(资金冻结)
public class PaymentTccService implements TccService {
@Override
public void tryOperation(TccOperation op) {
// 冻结资金
accountService.freezeFunds(op.getUserId(), op.getAmount());
}
@Override
public void confirmOperation(TccOperation op) {
// 确认支付
accountService.confirmPayment(op.getUserId(), op.getAmount());
}
@Override
public void cancelOperation(TccOperation op) {
// 解冻资金
accountService.unfreezeFunds(op.getUserId(), op.getAmount());
}
}
(3)Saga服务设计
// Saga步骤定义
public class SagaStep {
private String serviceName;
private String operation;
private CompensationAction compensation; // 补偿操作
// 执行正向操作
public void execute() {
// 调用对应服务执行操作
}
// 执行补偿操作
public void compensate() {
compensation.execute();
}
}
// Saga事务管理器
public class SagaTransactionManager {
public void execute(List<SagaStep> steps) {
// 按顺序执行各步骤
for (SagaStep step : steps) {
try {
step.execute();
} catch (Exception e) {
// 执行补偿(逆向)
compensate(steps, step);
throw e;
}
}
}
private void compensate(List<SagaStep> steps, SagaStep failedStep) {
// 逆向执行补偿(从失败点开始)
for (int i = steps.indexOf(failedStep); i >= 0; i--) {
steps.get(i).compensate();
}
}
}
4. 事务执行流程
文章中的mermaid 经常报错 直接生成图片 贴出来
5. 关键设计要点
-
事务边界划分:
- TCC用于资金、库存等核心资源操作
- Saga用于订单创建、物流调度等非核心流程
-
补偿机制协调:
- TCC补偿由事务协调器统一控制
- Saga补偿由Saga管理器独立处理
- 两者补偿操作互不依赖
-
状态管理:
- 使用分布式事务ID贯穿整个混合事务
- TCC和Saga共享同一事务上下文
-
错误处理策略:
- Saga失败 → 触发TCC补偿
- TCC失败 → 直接终止整个事务
- 混合失败 → 记录详细日志供人工介入
-
监控集成:
- 统一监控TCC和Saga的执行状态
- 设置不同的告警阈值(TCC更严格)
6. 技术实现建议
-
框架选择:
- TCC:Seata/TCC-Transaction
- Saga:自定义实现或Eventuate Tram
- 编排:Camunda/自研编排引擎
-
数据库设计:
- 共享事务表记录混合事务状态
- TCC和Saga状态分开存储但关联同一事务ID
-
通信机制:
- 使用消息队列解耦TCC和Saga服务
- 事件总线传递事务状态变更
-
部署架构:
- TCC服务集群独立部署保证高可用
- Saga服务可水平扩展应对高并发
7. 典型应用场景
-
电商下单:
- TCC:库存锁定、支付冻结
- Saga:订单创建、物流调度
-
供应链管理:
- TCC:采购订单确认、库存预留
- Saga:供应商通知、物流安排
-
金融系统:
- TCC:资金转账、账户扣减
- Saga:交易记录、通知发送
这种混合架构能在保证核心业务强一致性的同时,提高非核心业务的处理效率,是微服务架构中处理复杂事务场景的有效方案。
(二) 混合架构中TCC和Saga事务的超时处理方案
1. TCC事务超时处理
核心原则:严格超时控制,防止资源永久锁定
(1)Try阶段超时处理
// TCC超时监控器
public class TccTimeoutMonitor {
private long tryTimeout = 30000; // 30秒超时
public void monitorTryOperation(String transactionId) {
long startTime = System.currentTimeMillis();
while (true) {
// 检查Try阶段是否完成
if (tccStatusService.isTryCompleted(transactionId)) {
return; // 正常完成
}
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > tryTimeout) {
// 触发强制取消
tccManager.forceCancel(transactionId);
break;
}
Thread.sleep(1000); // 每秒检查一次
}
}
}
(2)Confirm/Cancel阶段超时处理
// 确认阶段超时处理
public void handleConfirmTimeout(String transactionId) {
// 1. 记录超时日志
log.warn("TCC Confirm超时: {}", transactionId);
// 2. 尝试强制确认(可能部分成功)
try {
tccManager.forceConfirm(transactionId);
} catch (Exception e) {
// 3. 记录失败并触发人工干预
alertService.raiseCriticalAlert("强制确认失败", transactionId);
}
}
// 取消阶段超时处理
public void handleCancelTimeout(String transactionId) {
// 1. 记录超时日志
log.warn("TCC Cancel超时: {}", transactionId);
// 2. 尝试强制取消(释放资源)
try {
tccManager.forceCancel(transactionId);
} catch (Exception e) {
// 3. 记录失败并触发人工干预
alertService.raiseCriticalAlert("强制取消失败", transactionId);
}
}
(3)超时配置建议
阶段 | 推荐超时时间 | 说明 |
---|---|---|
Try阶段 | 30秒 | 防止长时间占用预留资源 |
Confirm阶段 | 60秒 | 允许稍长处理时间 |
Cancel阶段 | 60秒 | 必须确保资源最终释放 |
2. Saga事务超时处理
核心原则:灵活重试+最终一致性
(1)步骤级超时处理
// Saga步骤执行器
public class SagaStepExecutor {
private long stepTimeout = 10000; // 10秒超时
public void executeWithTimeout(SagaStep step) {
Future<?> future = executorService.submit(() -> {
step.execute();
});
try {
future.get(stepTimeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// 超时处理
future.cancel(true); // 中断执行
log.warn("Saga步骤超时: {}", step.getServiceName());
throw new SagaTimeoutException(step);
}
}
}
(2)事务级超时处理
// Saga事务管理器
public class SagaTransactionManager {
private long transactionTimeout = 300000; // 5分钟超时
public void executeWithTimeout(List<SagaStep> steps) {
long startTime = System.currentTimeMillis();
try {
for (SagaStep step : steps) {
executeWithTimeout(step);
// 检查整体超时
if (System.currentTimeMillis() - startTime > transactionTimeout) {
throw new SagaGlobalTimeoutException();
}
}
} catch (SagaTimeoutException e) {
// 触发补偿
compensate(steps, e.getFailedStep());
}
}
}
(3)超时补偿策略
// 超时后的补偿逻辑
private void compensate(List<SagaStep> steps, SagaStep failedStep) {
// 1. 记录超时补偿日志
log.error("Saga超时补偿: {}", failedStep.getServiceName());
// 2. 逆向执行补偿(从失败点开始)
for (int i = steps.indexOf(failedStep); i >= 0; i--) {
try {
steps.get(i).compensate();
} catch (Exception e) {
// 补偿失败记录
log.error("补偿失败: {}", steps.get(i).getServiceName());
}
}
// 3. 标记事务状态为"超时补偿"
transactionStatusService.markAsCompensated(steps.get(0).getTransactionId());
}
3. 混合架构中的协同处理
(1)TCC与Saga超时联动
文章中的mermaid 经常报错 直接生成图片 贴出来
(2)关键处理规则
-
优先级原则:
- TCC超时必须立即处理(防止资源泄漏)
- Saga超时可尝试重试后补偿
-
状态同步:
- TCC和Saga共享同一事务ID
- 任一超时都会影响整体事务状态
-
告警分级:
- TCC超时 → 立即告警(P0级)
- Saga超时 → 延迟告警(P1级)
4. 监控与告警配置
(1)监控指标
指标类型 | TCC监控点 | Saga监控点 |
---|---|---|
超时次数 | Try/Confirm/Cancel超时次数 | 步骤/Saga事务超时次数 |
当前超时事务数 | 各阶段超时事务数 | 各步骤超时事务数 |
平均超时时间 | 各阶段平均超时时间 | 各步骤平均超时时间 |
(2)告警策略
# 告警配置示例
alerts:
tcc:
try_timeout:
threshold: 5 # 5次/分钟
severity: P0
confirm_timeout:
threshold: 3
severity: P0
saga:
step_timeout:
threshold: 10
severity: P1
transaction_timeout:
threshold: 2
severity: P1
5. 最佳实践建议
-
TCC超时:
- 设置合理的Try阶段超时(通常30秒内)
- 强制取消必须保证最终执行(可重试多次)
- 记录超时时的资源锁定状态
-
Saga超时:
- 步骤级超时可设置较短(如10秒)
- 事务级超时可设置较长(如5分钟)
- 补偿失败后标记为"人工处理"
-
混合架构:
- 统一超时监控看板
- 设置TCC超时优先级高于Saga
- 超时后自动触发补偿流程
通过以上设计,可以在混合架构中有效处理TCC和Saga的事务超时问题,既保证核心业务的强一致性,又维持非核心业务的高可用性。
(三) 混合架构中TCC与Saga事务回滚策略差异设计
1. 核心设计原则
维度 | TCC模式 | Saga模式 |
---|---|---|
回滚触发点 | Confirm阶段失败或超时 | 任一步骤执行失败 |
回滚粒度 | 整体事务回滚 | 步骤级回滚(可部分补偿) |
回滚保证 | 必须完全回滚(强一致性) | 最终一致(允许延迟补偿) |
回滚复杂度 | 较高(需协调多个服务) | 较低(各服务独立补偿) |
2. TCC模式回滚策略设计
(1)回滚触发条件
// TCC回滚触发器
public class TccRollbackTrigger {
public void checkRollbackConditions(String transactionId) {
// 1. Confirm阶段失败
if (tccStatusService.isConfirmFailed(transactionId)) {
triggerFullRollback(transactionId);
}
// 2. Try阶段超时(已强制取消)
else if (tccTimeoutMonitor.isTryTimedOut(transactionId)) {
// 已通过forceCancel处理,无需重复回滚
}
}
}
(2)完整回滚流程
文章中的mermaid 经常报错 直接生成图片 贴出来
(3)关键设计要点
- 原子性保证:
- 使用分布式事务ID贯穿所有Cancel操作
- 采用两阶段提交思想协调多个服务的Cancel
- 幂等设计:
// 服务端Cancel操作必须幂等 public void cancelOperation(String transactionId) { if (cancelLogService.isAlreadyCancelled(transactionId)) { return; // 已取消过则直接返回 } // 执行实际取消逻辑 // ... cancelLogService.recordCancellation(transactionId); }
- 超时处理:
- Try阶段超时后已通过forceCancel处理,不再重复回滚
3. Saga模式回滚策略设计
(1)步骤级回滚机制
// Saga步骤执行器
public class SagaStepExecutor {
public void executeWithCompensation(SagaStep step) {
try {
step.execute();
} catch (Exception e) {
// 立即触发补偿(逆向操作)
step.compensate();
// 可选:记录失败步骤供人工处理
failureTracker.recordFailedStep(step);
// 抛出异常终止后续步骤
throw new SagaStepFailedException(step);
}
}
}
(2)事务级回滚流程
文章中的mermaid 经常报错 直接生成图片 贴出来
(3)关键设计要点
- 补偿链设计:
- 每个步骤必须提供独立的补偿操作
- 补偿操作按执行逆序执行(LIFO原则)
- 状态管理:
// 事务状态机 public enum SagaState { CREATED, IN_PROGRESS, COMPENSATING, FAILED, COMPLETED } // 状态变更时触发补偿 public void transitionToCompensating(String transactionId) { // 1. 记录状态变更 // 2. 获取当前执行到的步骤 // 3. 从该步骤开始逆向补偿 }
- 部分成功处理:
- 可配置是否允许部分步骤成功(如订单创建成功但支付失败时,只回滚支付部分)
4. 混合架构中的协同回滚设计
(1)TCC与Saga回滚联动
文章中的mermaid 经常报错 直接生成图片 贴出来
(2)差异处理策略
场景 | TCC处理方式 | Saga处理方式 |
---|---|---|
单个服务失败 | 触发整体Cancel | 仅补偿失败步骤 |
部分步骤失败 | 不适用(必须全部成功) | 可配置部分补偿 |
超时导致失败 | 强制Cancel | 补偿已执行步骤 |
人工干预需求 | 记录超时状态供人工处理 | 标记失败步骤供人工补偿 |
5. 监控与告警差异
(1)TCC监控重点
# TCC监控配置
tcc:
monitoring:
focus:
- confirm_failure_rate # Confirm失败率
- cancel_timeout_count # Cancel超时次数
alert:
- condition: confirm_failure_rate > 0.1
severity: P0
(2)Saga监控重点
# Saga监控配置
saga:
monitoring:
focus:
- step_failure_count # 步骤失败次数
- compensation_latency # 补偿延迟
alert:
- condition: step_failure_count > 5
severity: P1
6. 最佳实践建议
-
TCC回滚:
- 设计完善的Cancel接口(必须幂等)
- 设置合理的超时时间(Try阶段通常30秒)
- 记录详细的回滚日志供审计
-
Saga回滚:
- 每个步骤必须提供独立的补偿操作
- 补偿操作应尽量轻量级(避免补偿失败)
- 可配置部分补偿策略(根据业务需求)
-
混合架构:
- 统一事务状态管理(TCC和Saga共享事务ID)
- 设置不同的回滚优先级(TCC > Saga)
- 提供人工干预接口(处理复杂回滚场景)
通过这种差异化的设计,可以在混合架构中既保证核心业务的强一致性(TCC),又保持非核心业务的高可用性(Saga),同时确保各种失败场景都能得到妥善处理。
(四) Saga补偿失败时触发TCC补偿的操作设计
1. 触发条件判断
当Saga事务执行过程中出现以下情况时需要触发TCC补偿:
- Saga步骤执行失败且无法通过补偿恢复
- Saga补偿操作失败(逆向操作执行出错)
- Saga事务整体超时导致无法完成
2. 触发流程设计
文章中的mermaid 经常报错 直接生成图片 贴出来
3. 关键实现步骤
(1)Saga端处理
// Saga事务管理器中的失败处理逻辑
public void handleSagaFailure(String transactionId) {
// 1. 记录Saga失败状态
sagaStatusService.markAsFailed(transactionId);
// 2. 获取关联的TCC事务ID(通过事务上下文关联)
String tccTransactionId = transactionContextService.getTccTransactionId(transactionId);
if (tccTransactionId != null) {
// 3. 触发TCC补偿
transactionOrchestrator.triggerTccCancel(tccTransactionId);
}
// 4. 记录失败详情供人工处理
failureTracker.recordSagaFailure(transactionId);
}
(2)事务编排器协调
// 事务编排器中的TCC补偿触发器
public class TransactionOrchestrator {
private TccManager tccManager;
public void triggerTccCancel(String tccTransactionId) {
try {
// 1. 记录补偿触发日志
log.info("触发TCC补偿: {}", tccTransactionId);
// 2. 执行TCC Cancel阶段
tccManager.executeCancel(tccTransactionId);
// 3. 更新事务状态为"已补偿"
transactionStatusService.markAsCompensated(tccTransactionId);
} catch (Exception e) {
// 4. 处理TCC补偿失败
handleTccCompensateFailure(tccTransactionId, e);
}
}
private void handleTccCompensateFailure(String tccTransactionId, Exception e) {
// 记录TCC补偿失败日志
log.error("TCC补偿失败: {}", tccTransactionId, e);
// 可选:触发人工干预流程
alertService.raiseCriticalAlert("TCC补偿失败", tccTransactionId);
}
}
(3)TCC端处理
// TCC管理器中的Cancel执行
public class TccManager {
public void executeCancel(String transactionId) {
// 1. 获取所有参与TCC的服务
List<TccService> services = tccServiceRegistry.getServices(transactionId);
// 2. 按依赖顺序执行Cancel(可能需要反向顺序)
for (TccService service : services) {
try {
service.cancelOperation(transactionId);
} catch (Exception e) {
// 记录单个服务Cancel失败
log.error("服务 {} Cancel失败", service.getName(), e);
// 可选择继续执行其他服务的Cancel
}
}
}
}
4. 关键设计要点
(1)事务关联机制
- 事务ID关联:
- 在Saga事务开始时记录关联的TCC事务ID
- 通过分布式事务上下文(如ThreadLocal或消息头)传递
- 状态同步:
- Saga和TCC共享同一事务状态机
- 状态变更时通知所有相关方
(2)补偿触发策略
触发场景 | 处理方式 |
---|---|
Saga步骤执行失败 | 立即触发TCC Cancel |
Saga补偿操作失败 | 记录失败后触发TCC Cancel |
Saga事务超时 | 强制终止Saga并触发TCC Cancel |
TCC Cancel自身失败 | 记录失败并标记为"需人工处理" |
(3)错误处理流程
文章中的mermaid 经常报错 直接生成图片 贴出来
5. 监控与告警配置
(1)监控指标
monitoring:
saga_t