微服务架构下分布式事务一致性保障方案:Saga模式与TCC模式深度对比

深夜诗人
深夜诗人 2025-12-07T21:18:00+08:00
0 0 0

引言

在微服务架构盛行的今天,传统的单体应用已经无法满足现代业务系统的复杂需求。微服务通过将大型应用拆分为多个独立的服务,提高了系统的可维护性、可扩展性和部署灵活性。然而,这种架构模式也带来了新的挑战——分布式事务一致性问题。

当一个业务操作需要跨越多个微服务时,如何确保这些分散的操作要么全部成功,要么全部失败,成为了一个核心难题。传统的ACID事务无法直接应用到分布式环境中,因为分布式事务涉及网络通信、服务调用等复杂因素,容易出现数据不一致的情况。

本文将深入分析微服务架构中分布式事务处理的核心挑战,并详细对比两种主流的分布式事务解决方案:Saga模式和TCC(Try-Confirm-Cancel)模式。通过理论分析、代码示例和最佳实践,为企业级分布式事务解决方案提供设计思路和技术指导。

微服务架构下的分布式事务挑战

1.1 分布式事务的本质问题

在微服务架构中,每个服务都拥有独立的数据存储,服务之间的交互通过API调用完成。当一个业务流程需要跨多个服务时,就产生了分布式事务的需求。分布式事务的核心挑战在于:

  • 网络可靠性:服务间的通信可能因为网络故障、超时等问题而失败
  • 数据一致性:如何保证多个服务的数据状态最终一致
  • 事务原子性:整个业务流程要么全部成功,要么全部回滚
  • 性能开销:分布式事务会带来额外的网络延迟和系统复杂度

1.2 传统ACID事务的局限性

在单体应用中,ACID(原子性、一致性、隔离性、持久性)事务能够很好地保证数据的一致性。但在微服务架构下,由于服务分布在不同的节点上,传统的本地事务无法跨越网络边界,因此需要采用新的分布式事务处理机制。

1.3 分布式事务的分类

根据分布式事务的实现方式,可以分为以下几类:

  • 强一致性方案:如两阶段提交(2PC)、三阶段提交(3PC)
  • 最终一致性方案:如Saga模式、TCC模式
  • 混合方案:结合多种模式的优势

Saga模式详解

2.1 Saga模式基本原理

Saga模式是一种长事务的解决方案,它将一个大的分布式事务分解为多个小的本地事务,每个本地事务都有对应的补偿操作。当整个业务流程失败时,通过执行相应的补偿操作来撤销已经完成的操作。

核心思想

Saga模式的核心思想是将复杂的业务流程拆分为一系列可逆的小步骤,每个步骤都是一个独立的事务。如果某个步骤失败,就按照相反的顺序执行补偿操作,使得整个流程回到初始状态。

2.2 Saga模式的两种实现方式

2.2.1 协议式Saga(Choreography)

在协议式Saga中,每个服务都负责协调自己的业务逻辑和补偿逻辑。服务之间通过消息传递来协调执行顺序。

// Saga协调器示例
@Component
public class OrderSagaCoordinator {
    
    private List<SagaStep> steps = new ArrayList<>();
    
    public void executeOrderProcess(OrderRequest request) {
        try {
            // 执行订单创建步骤
            steps.add(new OrderCreationStep());
            steps.add(new PaymentProcessingStep());
            steps.add(new InventoryReservationStep());
            
            for (SagaStep step : steps) {
                step.execute();
            }
            
        } catch (Exception e) {
            // 回滚已执行的步骤
            rollbackSteps();
        }
    }
    
    private void rollbackSteps() {
        // 逆序回滚所有已执行的步骤
        for (int i = steps.size() - 1; i >= 0; i--) {
            steps.get(i).rollback();
        }
    }
}

// 具体步骤实现
public class OrderCreationStep implements SagaStep {
    
    @Override
    public void execute() throws Exception {
        // 创建订单逻辑
        Order order = new Order();
        order.setId(UUID.randomUUID().toString());
        order.setStatus("CREATED");
        
        // 保存订单到数据库
        orderRepository.save(order);
        System.out.println("订单创建成功: " + order.getId());
    }
    
    @Override
    public void rollback() {
        // 回滚订单创建
        // 删除已创建的订单记录
        System.out.println("回滚订单创建操作");
    }
}

2.2.2 协调式Saga(Orchestration)

在协调式Saga中,有一个中心化的协调器来管理整个流程的执行和回滚。每个服务只负责执行自己的业务逻辑,而不需要关心其他服务的状态。

// 协调式Saga示例
@Component
public class OrderSagaOrchestrator {
    
    private final OrderService orderService;
    private final PaymentService paymentService;
    private final InventoryService inventoryService;
    
    public OrderSagaOrchestrator(OrderService orderService, 
                                PaymentService paymentService,
                                InventoryService inventoryService) {
        this.orderService = orderService;
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }
    
    public void processOrder(String orderId) {
        try {
            // 1. 创建订单
            orderService.createOrder(orderId);
            
            // 2. 处理支付
            paymentService.processPayment(orderId);
            
            // 3. 预留库存
            inventoryService.reserveInventory(orderId);
            
            // 4. 完成订单
            orderService.completeOrder(orderId);
            
        } catch (Exception e) {
            // 异常处理:执行补偿操作
            compensateOrderProcess(orderId);
        }
    }
    
    private void compensateOrderProcess(String orderId) {
        try {
            // 逆序执行补偿操作
            orderService.cancelOrder(orderId);
            paymentService.refundPayment(orderId);
            inventoryService.releaseInventory(orderId);
        } catch (Exception e) {
            // 记录补偿失败的日志,需要人工干预
            log.error("补偿操作失败,订单ID: " + orderId, e);
        }
    }
}

2.3 Saga模式的优缺点分析

优点:

  1. 实现简单:每个服务只需要关注自己的业务逻辑和补偿逻辑
  2. 性能较好:避免了长时间的锁等待
  3. 可扩展性强:可以轻松添加新的服务节点
  4. 容错性好:单个服务失败不会影响整个流程

缺点:

  1. 补偿逻辑复杂:需要为每个业务操作编写对应的补偿逻辑
  2. 数据一致性保证弱:在执行过程中可能出现数据不一致状态
  3. 调试困难:分布式环境下问题定位较为困难
  4. 幂等性要求高:补偿操作必须具备幂等性

TCC模式详解

3.1 TCC模式基本原理

TCC(Try-Confirm-Cancel)是一种二阶段提交的分布式事务解决方案。它将业务流程分解为三个阶段:

  1. Try阶段:尝试执行业务操作,完成资源的预留和检查
  2. Confirm阶段:确认执行业务操作,正式提交事务
  3. Cancel阶段:取消执行业务操作,回滚已预留的资源

3.2 TCC模式的实现机制

3.2.1 Try阶段

在Try阶段,服务会检查资源是否可用,并预留相应的资源。这个阶段不能进行真正的业务操作,只能做一些检查和预处理。

// TCC服务示例
@Service
public class InventoryTccService {
    
    @Autowired
    private InventoryRepository inventoryRepository;
    
    // Try阶段:预留库存
    public void tryReserve(String orderId, String productId, int quantity) {
        // 检查库存是否充足
        Inventory inventory = inventoryRepository.findByProductId(productId);
        if (inventory == null || inventory.getAvailableQuantity() < quantity) {
            throw new BusinessException("库存不足");
        }
        
        // 预留库存
        inventory.setReservedQuantity(inventory.getReservedQuantity() + quantity);
        inventoryRepository.save(inventory);
        
        System.out.println("预留库存成功: " + productId + ", 数量: " + quantity);
    }
    
    // Confirm阶段:确认预留库存
    public void confirmReserve(String orderId, String productId, int quantity) {
        // 确认库存预留
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setReservedQuantity(inventory.getReservedQuantity() - quantity);
        inventory.setAvailableQuantity(inventory.getAvailableQuantity() - quantity);
        inventoryRepository.save(inventory);
        
        System.out.println("确认库存预留成功: " + productId + ", 数量: " + quantity);
    }
    
    // Cancel阶段:取消库存预留
    public void cancelReserve(String orderId, String productId, int quantity) {
        // 取消库存预留
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setReservedQuantity(inventory.getReservedQuantity() - quantity);
        inventoryRepository.save(inventory);
        
        System.out.println("取消库存预留成功: " + productId + ", 数量: " + quantity);
    }
}

3.2.2 TCC协调器

// TCC事务协调器
@Component
public class TccTransactionCoordinator {
    
    private final List<TccParticipant> participants = new ArrayList<>();
    
    public void executeTccTransaction(TccTransaction transaction) {
        try {
            // 第一阶段:Try操作
            for (TccParticipant participant : participants) {
                participant.tryExecute();
            }
            
            // 第二阶段:Confirm操作
            for (TccParticipant participant : participants) {
                participant.confirmExecute();
            }
            
            System.out.println("TCC事务执行成功");
            
        } catch (Exception e) {
            // 出现异常,执行Cancel操作
            cancelTccTransaction();
            throw new RuntimeException("TCC事务失败", e);
        }
    }
    
    private void cancelTccTransaction() {
        // 逆序执行Cancel操作
        for (int i = participants.size() - 1; i >= 0; i--) {
            participants.get(i).cancelExecute();
        }
        System.out.println("TCC事务回滚完成");
    }
}

// TCC参与者接口
public interface TccParticipant {
    void tryExecute() throws Exception;
    void confirmExecute() throws Exception;
    void cancelExecute() throws Exception;
}

3.3 TCC模式的优缺点分析

优点:

  1. 强一致性保证:通过二阶段提交机制,确保数据的一致性
  2. 灵活性高:可以自定义每个阶段的具体逻辑
  3. 事务可控:可以精确控制事务的执行和回滚过程
  4. 性能相对较好:相比传统两阶段提交,减少了锁等待时间

缺点:

  1. 实现复杂:需要为每个服务编写Try、Confirm、Cancel三个阶段的代码
  2. 业务侵入性强:服务需要按照TCC模式进行改造
  3. 补偿机制复杂:如果Confirm或Cancel失败,需要额外的重试和补偿机制
  4. 幂等性要求严格:所有操作都必须具备幂等性

Saga模式与TCC模式深度对比

4.1 实现复杂度对比

Saga模式实现复杂度

Saga模式的实现相对简单,主要体现在:

  • 服务改造成本低:只需要在每个服务中添加业务逻辑和补偿逻辑
  • 开发周期短:不需要对现有业务逻辑进行大规模重构
  • 维护成本低:补偿逻辑相对独立,易于维护

TCC模式实现复杂度

TCC模式的实现较为复杂:

  • 改造成本高:需要为每个服务编写三个阶段的代码
  • 开发周期长:需要深入理解业务流程并进行详细设计
  • 维护成本高:需要同时维护Try、Confirm、Cancel三个逻辑

4.2 性能特点对比

Saga模式性能特点

// 性能测试示例
public class PerformanceComparison {
    
    // Saga模式性能测试
    public void sagaPerformanceTest() {
        long startTime = System.currentTimeMillis();
        
        // 模拟Saga流程执行
        for (int i = 0; i < 1000; i++) {
            // 执行单个步骤
            executeStep(i);
        }
        
        long endTime = System.currentTimeMillis();
        System.out.println("Saga模式执行时间: " + (endTime - startTime) + "ms");
    }
    
    // TCC模式性能测试
    public void tccPerformanceTest() {
        long startTime = System.currentTimeMillis();
        
        // 模拟TCC流程执行
        for (int i = 0; i < 1000; i++) {
            // 执行Try、Confirm、Cancel三个阶段
            tryExecute(i);
            confirmExecute(i);
            cancelExecute(i);
        }
        
        long endTime = System.currentTimeMillis();
        System.out.println("TCC模式执行时间: " + (endTime - startTime) + "ms");
    }
}

性能对比分析

特性 Saga模式 TCC模式
执行效率 较高 中等
网络开销 较低 较高
锁竞争 存在
响应时间 快速 相对慢

4.3 数据一致性保证对比

Saga模式一致性保证

Saga模式采用最终一致性模型:

// 最终一致性示例
@Component
public class EventuallyConsistentService {
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    public void processOrderWithEventualConsistency(OrderRequest request) {
        // 1. 执行业务操作(异步)
        CompletableFuture.runAsync(() -> {
            try {
                // 创建订单
                orderService.createOrder(request);
                
                // 更新库存(异步)
                inventoryService.updateInventory(request.getProductId(), 
                                               request.getQuantity());
                
                // 发送消息到消息队列
                messageQueue.send("order.created", request);
                
            } catch (Exception e) {
                // 记录错误日志
                log.error("订单处理失败", e);
            }
        });
        
        // 2. 异步补偿机制
        CompletableFuture.delayedExecutor(30, TimeUnit.SECONDS)
                        .execute(() -> {
                            if (!isOrderCompleted(request.getOrderId())) {
                                performCompensation(request);
                            }
                        });
    }
}

TCC模式一致性保证

TCC模式提供强一致性保证:

// 强一致性示例
@Component
public class StrongConsistentService {
    
    @Transactional
    public void processOrderWithStrongConsistency(OrderRequest request) {
        try {
            // 1. Try阶段:预留资源
            inventoryService.tryReserve(request.getProductId(), 
                                      request.getQuantity());
            paymentService.tryDeduct(request.getAmount());
            
            // 2. Confirm阶段:正式提交
            inventoryService.confirmReserve(request.getProductId(), 
                                          request.getQuantity());
            paymentService.confirmDeduct(request.getAmount());
            
            // 3. 更新订单状态
            orderService.updateOrderStatus(request.getOrderId(), "CONFIRMED");
            
        } catch (Exception e) {
            // 4. Cancel阶段:回滚操作
            try {
                inventoryService.cancelReserve(request.getProductId(), 
                                             request.getQuantity());
                paymentService.cancelDeduct(request.getAmount());
            } catch (Exception cancelException) {
                // 记录补偿失败,需要人工干预
                log.error("补偿失败", cancelException);
            }
            
            throw new RuntimeException("订单处理失败", e);
        }
    }
}

4.4 适用场景对比

Saga模式适用场景

  1. 业务流程简单:适合业务逻辑相对简单的分布式事务
  2. 对一致性要求不严格:可以接受短暂的数据不一致
  3. 需要快速开发上线:实现成本较低,开发周期短
  4. 异步处理需求:适合异步处理的场景
// 适用Saga模式的业务场景
public class OrderProcessingService {
    
    // 订单创建流程 - 适合Saga模式
    public void createOrder(OrderRequest request) {
        // 1. 创建订单
        orderService.create(request);
        
        // 2. 处理支付
        paymentService.process(request.getPayment());
        
        // 3. 发送通知
        notificationService.sendNotification(request);
        
        // 4. 更新统计
        statisticsService.updateStatistics(request);
    }
}

TCC模式适用场景

  1. 强一致性要求:需要保证数据绝对一致的场景
  2. 资源预留需求:需要提前预留资源的业务流程
  3. 复杂业务逻辑:业务流程复杂,需要精确控制事务边界
  4. 金融交易系统:对数据一致性要求极高的场景
// 适用TCC模式的业务场景
public class FinancialTransactionService {
    
    // 转账流程 - 适合TCC模式
    public void transferMoney(TransferRequest request) {
        try {
            // 1. Try阶段:检查余额并预留资金
            accountService.tryReserve(request.getFromAccount(), 
                                    request.getAmount());
            accountService.tryReserve(request.getToAccount(), 
                                    request.getAmount());
            
            // 2. Confirm阶段:正式转账
            accountService.confirmTransfer(request.getFromAccount(), 
                                         request.getToAccount(), 
                                         request.getAmount());
            
        } catch (Exception e) {
            // 3. Cancel阶段:回滚转账
            accountService.cancelTransfer(request.getFromAccount(), 
                                        request.getToAccount(), 
                                        request.getAmount());
            throw new RuntimeException("转账失败", e);
        }
    }
}

实际应用最佳实践

5.1 Saga模式最佳实践

5.1.1 补偿逻辑设计原则

// 补偿逻辑设计示例
public class CompensationBestPractices {
    
    // 1. 确保补偿操作幂等性
    public void idempotentCompensation(String orderId) {
        // 检查是否已经执行过补偿
        if (compensationRecordRepository.existsByOrderId(orderId)) {
            return; // 已经补偿过,直接返回
        }
        
        try {
            // 执行补偿操作
            executeCompensationLogic(orderId);
            
            // 记录补偿完成状态
            compensationRecordRepository.save(new CompensationRecord(orderId, "COMPLETED"));
        } catch (Exception e) {
            // 记录补偿失败
            compensationRecordRepository.save(new CompensationRecord(orderId, "FAILED"));
            throw e;
        }
    }
    
    // 2. 异步执行补偿操作
    @Async
    public void asyncCompensation(String orderId) {
        try {
            Thread.sleep(1000); // 模拟异步处理
            executeCompensationLogic(orderId);
        } catch (Exception e) {
            // 重试机制
            retryCompensation(orderId, 3);
        }
    }
    
    private void retryCompensation(String orderId, int maxRetries) {
        for (int i = 0; i < maxRetries; i++) {
            try {
                executeCompensationLogic(orderId);
                return;
            } catch (Exception e) {
                if (i == maxRetries - 1) {
                    throw new RuntimeException("补偿重试失败", e);
                }
                try {
                    Thread.sleep(2000 * (i + 1)); // 指数退避
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("补偿重试被中断", ie);
                }
            }
        }
    }
}

5.1.2 Saga协调器优化

// Saga协调器优化示例
@Component
public class OptimizedSagaCoordinator {
    
    private final Map<String, SagaContext> sagaContexts = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = 
        Executors.newScheduledThreadPool(2);
    
    public void executeWithTimeout(SagaProcess process, long timeoutMs) {
        String sagaId = UUID.randomUUID().toString();
        SagaContext context = new SagaContext(sagaId, process);
        sagaContexts.put(sagaId, context);
        
        // 设置超时处理
        scheduler.schedule(() -> {
            if (sagaContexts.containsKey(sagaId)) {
                handleTimeout(sagaId);
            }
        }, timeoutMs, TimeUnit.MILLISECONDS);
        
        try {
            process.execute();
            completeSaga(sagaId);
        } catch (Exception e) {
            rollbackSaga(sagaId);
            throw e;
        }
    }
    
    private void handleTimeout(String sagaId) {
        SagaContext context = sagaContexts.get(sagaId);
        if (context != null && !context.isCompleted()) {
            // 执行超时补偿
            context.getProcess().handleTimeout();
            completeSaga(sagaId);
        }
    }
    
    private void completeSaga(String sagaId) {
        sagaContexts.remove(sagaId);
    }
    
    private void rollbackSaga(String sagaId) {
        SagaContext context = sagaContexts.get(sagaId);
        if (context != null) {
            context.getProcess().rollback();
            completeSaga(sagaId);
        }
    }
}

5.2 TCC模式最佳实践

5.2.1 TCC服务设计原则

// TCC服务设计示例
@Service
public class TccServiceDesign {
    
    // 1. Try操作必须是幂等的
    @Transactional
    public void tryReserve(String orderId, String productId, int quantity) {
        // 幂等性检查
        if (isTryOperationCompleted(orderId, productId)) {
            return; // 已经执行过,直接返回
        }
        
        // 执行Try操作
        Inventory inventory = inventoryRepository.findByProductId(productId);
        if (inventory.getAvailableQuantity() < quantity) {
            throw new BusinessException("库存不足");
        }
        
        // 预留资源
        inventory.setReservedQuantity(inventory.getReservedQuantity() + quantity);
        inventoryRepository.save(inventory);
        
        // 记录Try操作状态
        recordTryOperation(orderId, productId, "SUCCESS");
    }
    
    // 2. Confirm和Cancel操作必须具备事务性
    @Transactional
    public void confirmReserve(String orderId, String productId, int quantity) {
        // 检查Try操作是否成功
        if (!isTryOperationCompleted(orderId, productId)) {
            throw new BusinessException("Try操作未完成,无法Confirm");
        }
        
        // 执行Confirm操作
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setReservedQuantity(inventory.getReservedQuantity() - quantity);
        inventory.setAvailableQuantity(inventory.getAvailableQuantity() - quantity);
        inventoryRepository.save(inventory);
        
        // 记录Confirm操作状态
        recordConfirmOperation(orderId, productId, "SUCCESS");
    }
    
    @Transactional
    public void cancelReserve(String orderId, String productId, int quantity) {
        // 执行Cancel操作
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setReservedQuantity(inventory.getReservedQuantity() - quantity);
        inventoryRepository.save(inventory);
        
        // 记录Cancel操作状态
        recordCancelOperation(orderId, productId, "SUCCESS");
    }
}

5.2.2 TCC事务管理优化

// TCC事务管理优化示例
@Component
public class TccTransactionManager {
    
    private final Map<String, TccTransactionState> transactionStates = 
        new ConcurrentHashMap<>();
    
    public void executeTccTransaction(TccTransaction transaction) {
        String transactionId = UUID.randomUUID().toString();
        TccTransactionState state = new TccTransactionState(transactionId);
        
        try {
            // 1. 执行Try阶段
            executeTryPhase(transaction, state);
            
            // 2. 立即执行Confirm阶段
            executeConfirmPhase(transaction, state);
            
            // 3. 更新事务状态
            state.setStatus(TccTransactionStatus.COMMITTED);
            
        } catch (Exception e) {
            // 4. 执行回滚
            rollbackTccTransaction(transactionId, state);
            throw new RuntimeException("TCC事务执行失败", e);
        }
    }
    
    private void executeTryPhase(TccTransaction transaction, TccTransactionState state) {
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        
        for (TccParticipant participant : transaction.getParticipants()) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    participant.tryExecute();
                    state.addCompletedParticipant(participant.getName());
                } catch (Exception e) {
                    state.addFailedParticipant(participant.getName(), e);
                    throw new RuntimeException("Try阶段执行失败", e);
                }
            });
            futures.add(future);
        }
        
        // 等待所有Try操作完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                        .join();
    }
    
    private void executeConfirmPhase(TccTransaction transaction, TccTransactionState state) {
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        
        for (TccParticipant participant : transaction.getParticipants()) {
            if (state.isParticipantCompleted(participant.getName())) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        participant.confirmExecute();
                    } catch (Exception e) {
                        // 记录失败,但继续执行其他Confirm操作
                        log.error("Confirm阶段执行失败", e);
                    }
                });
                futures.add(future);
            }
        }
        
        // 异步执行Confirm操作
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                        .join();
    }
    
    private void rollbackTccTransaction(String transactionId, TccTransactionState state) {
        // 逆序执行Cancel操作
        List<String> participants = new ArrayList<>(state.getCompletedParticipants());
        Collections.reverse(participants);
        
        for (String participantName : participants) {
            try {
                // 获取对应的参与者并执行Cancel
                TccParticipant participant = getParticipantByName(participantName);
                participant.cancelExecute();
            } catch (Exception e) {
                log.error("回滚操作失败: " + participantName, e);
                // 发送告警通知
                notifyRollbackFailure(transactionId, participantName, e);
            }
        }
    }
}

总结与建议

6.1 选择原则总结

在实际项目中,选择合适的分布式事务解决方案需要综合考虑以下因素:

6.1.1 业务需求分析

  • 一致性要求:强一致性需求选择TCC模式,最终一致性需求可选Saga模式
  • 业务复杂度:简单业务流程适合Saga模式,复杂业务流程适合TCC模式
  • 性能要求:对性能要求高的场景,Saga模式通常表现更好

6.1.2 技术架构考量

  • 团队能力:团队技术实力强可选择TCC模式,一般团队建议从Saga模式开始
  • 改造成本:现有系统改造成本低的场景优先考虑Saga模式
  • 维护复杂度:长期维护需求高的项目,建议选择实现相对简单的方案

6.2 实施建议

6.2.1 分阶段实施策略

// 分阶段实施示例
public class PhasedImplementation {
    
    // 第一阶段:简单业务场景使用Saga模式
    public void phaseOne() {
        // 适用于订单创建、支付等
相关推荐
广告位招租

相似文章

    评论 (0)

    0/2000