混合事务架构设计(Saga + TCC)(一)、(二)、(三)、(四)

(一) 混合事务架构设计(Saga + TCC)

1. 架构设计原则
  1. 业务分层
    • 核心业务(资金/库存)使用TCC模式保证强一致性
    • 非核心业务(订单/物流)使用Saga模式提高吞吐量
  2. 事务边界清晰
    • 明确划分需要强一致性的操作和允许最终一致性的操作
  3. 补偿机制独立
    • TCC和Saga的补偿操作分开设计,互不干扰
  4. 监控统一
    • 建立统一的监控系统跟踪两种事务的执行状态
2. 架构分层设计
客户端请求
API网关
业务编排层
TCC服务集群
Saga服务集群
数据库/缓存
数据库/缓存
事件总线
监控系统
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. 事务执行流程
Client Orchestrator TCCManager SagaManager 发起混合事务 执行Try阶段 Try成功 执行Saga步骤 Saga成功 执行Confirm阶段 Confirm成功 返回成功 执行Cancel阶段 Cancel成功 返回失败 alt [Saga失败] Client Orchestrator TCCManager SagaManager
5. 关键设计要点
  1. 事务边界划分

    • TCC用于资金、库存等核心资源操作
    • Saga用于订单创建、物流调度等非核心流程
  2. 补偿机制协调

    • TCC补偿由事务协调器统一控制
    • Saga补偿由Saga管理器独立处理
    • 两者补偿操作互不依赖
  3. 状态管理

    • 使用分布式事务ID贯穿整个混合事务
    • TCC和Saga共享同一事务上下文
  4. 错误处理策略

    • Saga失败 → 触发TCC补偿
    • TCC失败 → 直接终止整个事务
    • 混合失败 → 记录详细日志供人工介入
  5. 监控集成

    • 统一监控TCC和Saga的执行状态
    • 设置不同的告警阈值(TCC更严格)
6. 技术实现建议
  1. 框架选择

    • TCC:Seata/TCC-Transaction
    • Saga:自定义实现或Eventuate Tram
    • 编排:Camunda/自研编排引擎
  2. 数据库设计

    • 共享事务表记录混合事务状态
    • TCC和Saga状态分开存储但关联同一事务ID
  3. 通信机制

    • 使用消息队列解耦TCC和Saga服务
    • 事件总线传递事务状态变更
  4. 部署架构

    • TCC服务集群独立部署保证高可用
    • Saga服务可水平扩展应对高并发
7. 典型应用场景
  1. 电商下单

    • TCC:库存锁定、支付冻结
    • Saga:订单创建、物流调度
  2. 供应链管理

    • TCC:采购订单确认、库存预留
    • Saga:供应商通知、物流安排
  3. 金融系统

    • 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超时联动

Orchestrator TCCManager SagaManager 执行Try阶段 Try完成 执行Saga步骤 触发补偿 执行Cancel阶段 强制取消 终止Saga alt [Saga超时] [TCC超时] Orchestrator TCCManager SagaManager

(2)关键处理规则

  1. 优先级原则

    • TCC超时必须立即处理(防止资源泄漏)
    • Saga超时可尝试重试后补偿
  2. 状态同步

    • TCC和Saga共享同一事务ID
    • 任一超时都会影响整体事务状态
  3. 告警分级

    • 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. 最佳实践建议
  1. TCC超时

    • 设置合理的Try阶段超时(通常30秒内)
    • 强制取消必须保证最终执行(可重试多次)
    • 记录超时时的资源锁定状态
  2. Saga超时

    • 步骤级超时可设置较短(如10秒)
    • 事务级超时可设置较长(如5分钟)
    • 补偿失败后标记为"人工处理"
  3. 混合架构

    • 统一超时监控看板
    • 设置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)完整回滚流程

Orchestrator TCCManager ServiceA ServiceB ServiceC 检测到Confirm失败 记录回滚状态 执行CancelA 执行CancelB 执行CancelC 返回回滚结果 Orchestrator TCCManager ServiceA ServiceB ServiceC

(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)事务级回滚流程

Orchestrator SagaManager ServiceA ServiceB 执行Saga步骤1 执行操作A 步骤1成功 执行Saga步骤2 执行操作B 步骤2失败 执行补偿B 执行补偿A 返回回滚结果 Orchestrator SagaManager ServiceA ServiceB

(3)关键设计要点

  • 补偿链设计
    • 每个步骤必须提供独立的补偿操作
    • 补偿操作按执行逆序执行(LIFO原则)
  • 状态管理
    // 事务状态机
    public enum SagaState {
        CREATED, IN_PROGRESS, COMPENSATING, FAILED, COMPLETED
    }
    
    // 状态变更时触发补偿
    public void transitionToCompensating(String transactionId) {
        // 1. 记录状态变更
        // 2. 获取当前执行到的步骤
        // 3. 从该步骤开始逆向补偿
    }
    
  • 部分成功处理
    • 可配置是否允许部分步骤成功(如订单创建成功但支付失败时,只回滚支付部分)
4. 混合架构中的协同回滚设计

(1)TCC与Saga回滚联动

Orchestrator TCCManager SagaManager 执行Saga步骤 触发补偿 执行Cancel阶段 强制取消 终止Saga alt [Saga步骤失败] [TCC Confirm失败] Orchestrator TCCManager SagaManager

(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. 最佳实践建议
  1. TCC回滚

    • 设计完善的Cancel接口(必须幂等)
    • 设置合理的超时时间(Try阶段通常30秒)
    • 记录详细的回滚日志供审计
  2. Saga回滚

    • 每个步骤必须提供独立的补偿操作
    • 补偿操作应尽量轻量级(避免补偿失败)
    • 可配置部分补偿策略(根据业务需求)
  3. 混合架构

    • 统一事务状态管理(TCC和Saga共享事务ID)
    • 设置不同的回滚优先级(TCC > Saga)
    • 提供人工干预接口(处理复杂回滚场景)

通过这种差异化的设计,可以在混合架构中既保证核心业务的强一致性(TCC),又保持非核心业务的高可用性(Saga),同时确保各种失败场景都能得到妥善处理。

(四) Saga补偿失败时触发TCC补偿的操作设计

1. 触发条件判断

当Saga事务执行过程中出现以下情况时需要触发TCC补偿:

  1. Saga步骤执行失败且无法通过补偿恢复
  2. Saga补偿操作失败(逆向操作执行出错)
  3. Saga事务整体超时导致无法完成
2. 触发流程设计
SagaManager TransactionOrchestrator TccManager ServiceA ServiceB 检测到Saga补偿失败 报告Saga事务失败 触发TCC Cancel阶段 执行CancelA 执行CancelB 返回Cancel结果 通知TCC补偿完成 SagaManager TransactionOrchestrator TccManager ServiceA ServiceB
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)错误处理流程

Saga补偿失败
是否关联TCC?
触发TCC Cancel
仅记录Saga失败
TCC Cancel成功?
标记事务完成
记录TCC补偿失败
触发人工干预
5. 监控与告警配置

(1)监控指标

monitoring:
  saga_t

你可能感兴趣的:(分布式理论&实践,java,开发语言)