【6.1.2 漫画分布式事务技术选型】

漫画分布式事务技术选型

🎯 学习目标:掌握架构师核心技能------分布式事务技术选型与一致性解决方案,构建高可靠的分布式系统


🎭 第一章:分布式事务模式对比

🤔 2PC vs 3PC vs TCC vs Saga

想象分布式事务就像不同的团队协作方式...

复制代码
🎭 分布式事务协作模式:

2PC (二阶段提交):
┌─────────────────────────────────────┐
│        协调者 (Coordinator)          │
│              │                      │
│    ┌─────────┼─────────┐            │
│    ▼         ▼         ▼            │
│ 参与者A   参与者B   参与者C          │
│ (准备)    (准备)    (准备)           │
│    │         │         │            │
│    ▼         ▼         ▼            │
│ (提交)    (提交)    (提交)           │
│                                    │
│ 特点:                              │
│ • 强一致性保证                      │
│ • 阻塞性问题                        │
│ • 单点故障风险                      │
│ • 适用:小规模关键业务              │
└─────────────────────────────────────┘

TCC (Try-Confirm-Cancel):
┌─────────────────────────────────────┐
│           业务活动管理器             │
│              │                      │
│    ┌─────────┼─────────┐            │
│    ▼         ▼         ▼            │
│ 服务A-Try 服务B-Try 服务C-Try       │
│ (资源预留) (资源预留) (资源预留)     │
│    │         │         │            │
│    ▼         ▼         ▼            │
│ Confirm   Confirm   Confirm         │
│ (确认)    (确认)    (确认)           │
│                                    │
│ 特点:                              │
│ • 业务侵入性强                      │
│ • 最终一致性                        │
│ • 性能较好                          │
│ • 适用:业务可拆分场景              │
└─────────────────────────────────────┘

Saga (长事务):
┌─────────────────────────────────────┐
│          Saga编排器                  │
│              │                      │
│    T1 → T2 → T3 → T4 → T5           │
│    │    │    │    │    │            │
│   C1 ← C2 ← C3 ← C4 ← C5            │
│ (事务)              (补偿)           │
│                                    │
│ 特点:                              │
│ • 长事务友好                        │
│ • 业务补偿逻辑                      │
│ • 最终一致性                        │
│ • 适用:复杂业务流程                │
└─────────────────────────────────────┘

📊 分布式事务技术详细对比

复制代码
📊 分布式事务技术对比:

┌─────────────┬─────────────┬─────────────┬─────────────┐
│    特性     │     2PC     │     TCC     │    Saga     │
├─────────────┼─────────────┼─────────────┼─────────────┤
│ 🔒 一致性   │    强一致    │   最终一致   │   最终一致   │
│ 🚀 性能     │     低      │     中      │     高      │
│ 🔧 复杂度   │    简单     │     高      │     中      │
│ 📊 吞吐量   │     低      │     中      │     高      │
│ 🛡️ 可靠性   │    中等     │     高      │     高      │
│ 💻 业务侵入 │     小      │     大      │     中      │
│ 🌐 适用场景 │  关键业务    │  核心交易    │  复杂流程   │
│ 🎯 推荐度   │     低      │     高      │     高      │
└─────────────┴─────────────┴─────────────┴─────────────┘

技术选型建议:
🎯 银行转账系统 → TCC (资金安全)
🎯 电商下单流程 → Saga (流程复杂)
🎯 库存扣减场景 → TCC (原子操作)
🎯 数据同步任务 → Saga (长时间运行)
🎯 支付系统 → TCC (强一致性要求)

🎯 分布式事务选型决策树

复制代码
🎯 分布式事务选型流程:

                    开始选型
                        │
                   ┌────▼────┐
                   │一致性要求│
                   └────┬────┘
                        │
         ┌──────────────┼──────────────┐
         ▼              ▼              ▼
     强一致性       最终一致性      高性能要求
         │              │              │
    ┌────▼────┐    ┌────▼────┐    ┌────▼────┐
    │关键业务  │    │复杂流程  │    │高并发   │
    └────┬────┘    └────┬────┘    └────┬────┘
         │              │              │
         ▼              ▼              ▼
    XA/2PC事务      Saga模式        异步消息
   (小规模场景)    (长事务场景)     (最终一致)

重要业务场景选型:
┌─────────────────┬─────────────┬─────────────┐
│   业务场景       │  推荐方案    │   备选方案   │
├─────────────────┼─────────────┼─────────────┤
│ 银行转账         │    TCC      │    XA       │
│ 电商下单         │   Saga      │   本地消息表 │
│ 库存扣减         │    TCC      │   分布式锁   │
│ 订单支付         │    TCC      │    2PC      │
│ 数据同步         │   Saga      │   消息队列   │
│ 批量处理         │   Saga      │   状态机    │
└─────────────────┴─────────────┴─────────────┘

🛠️ 第二章:Seata分布式事务框架

🏗️ Seata架构与模式

java 复制代码
// 🛠️ Seata分布式事务实战

/**
 * Seata配置中心
 */
@Configuration
@EnableAutoDataSourceProxy
public class SeataConfig {
    
    /**
     * AT模式数据源代理
     */
    @Bean
    @Primary
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }
    
    /**
     * TCC模式业务资源管理器
     */
    @Bean
    public TccTransactionManager tccTransactionManager() {
        return new TccTransactionManager();
    }
    
    /**
     * Saga状态机配置
     */
    @Bean
    public StateMachineEngine stateMachineEngine() {
        StateMachineEngineBuilder builder = StateMachineEngineBuilder.newBuilder();
        builder.setDataSource(dataSource())
               .setTransactionManager(platformTransactionManager())
               .setApplicationContext(applicationContext);
        return builder.build();
    }
}

/**
 * AT模式 - 自动补偿
 */
@Service
@Slf4j
public class OrderServiceAT {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private AccountServiceClient accountServiceClient;
    
    @Autowired
    private ProductServiceClient productServiceClient;
    
    /**
     * 创建订单 - AT模式全局事务
     */
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public Order createOrder(CreateOrderRequest request) {
        log.info("开始创建订单: userId={}", request.getUserId());
        
        try {
            // 1. 创建订单记录
            Order order = new Order();
            order.setUserId(request.getUserId());
            order.setProductId(request.getProductId());
            order.setQuantity(request.getQuantity());
            order.setAmount(request.getAmount());
            order.setStatus(OrderStatus.PENDING);
            order.setCreateTime(LocalDateTime.now());
            
            order = orderRepository.save(order);
            log.info("订单创建成功: orderId={}", order.getId());
            
            // 2. 扣减账户余额
            accountServiceClient.deductBalance(
                request.getUserId(), 
                request.getAmount()
            );
            log.info("账户扣款成功: userId={}, amount={}", 
                request.getUserId(), request.getAmount());
            
            // 3. 扣减商品库存
            productServiceClient.reduceStock(
                request.getProductId(), 
                request.getQuantity()
            );
            log.info("库存扣减成功: productId={}, quantity={}", 
                request.getProductId(), request.getQuantity());
            
            // 4. 更新订单状态
            order.setStatus(OrderStatus.SUCCESS);
            orderRepository.save(order);
            
            log.info("订单处理完成: orderId={}", order.getId());
            return order;
            
        } catch (Exception e) {
            log.error("订单创建失败: userId={}", request.getUserId(), e);
            throw new OrderException("订单创建失败: " + e.getMessage(), e);
        }
    }
}

/**
 * TCC模式 - 手动补偿
 */
@LocalTCC
@Service
@Slf4j
public class AccountServiceTCC {
    
    @Autowired
    private AccountRepository accountRepository;
    
    @Autowired
    private AccountFreezeRepository freezeRepository;
    
    /**
     * Try阶段 - 冻结资金
     */
    @TwoPhaseBusinessAction(
        name = "deductBalance",
        commitMethod = "confirmDeduct",
        rollbackMethod = "cancelDeduct"
    )
    public boolean deductBalance(
            BusinessActionContext context,
            @BusinessActionContextParameter("userId") Long userId,
            @BusinessActionContextParameter("amount") BigDecimal amount) {
        
        String xid = context.getXid();
        log.info("TCC Try阶段 - 冻结资金: xid={}, userId={}, amount={}", 
            xid, userId, amount);
        
        try {
            // 1. 检查账户余额
            Account account = accountRepository.findByUserId(userId);
            if (account == null) {
                throw new AccountException("账户不存在");
            }
            
            if (account.getBalance().compareTo(amount) < 0) {
                throw new InsufficientBalanceException("余额不足");
            }
            
            // 2. 冻结资金
            AccountFreeze freeze = new AccountFreeze();
            freeze.setXid(xid);
            freeze.setUserId(userId);
            freeze.setAmount(amount);
            freeze.setStatus(FreezeStatus.TRYING);
            freeze.setCreateTime(LocalDateTime.now());
            
            freezeRepository.save(freeze);
            
            // 3. 扣减可用余额
            account.setBalance(account.getBalance().subtract(amount));
            account.setFrozenAmount(account.getFrozenAmount().add(amount));
            accountRepository.save(account);
            
            log.info("资金冻结成功: xid={}, userId={}, amount={}", 
                xid, userId, amount);
            return true;
            
        } catch (Exception e) {
            log.error("资金冻结失败: xid={}, userId={}, amount={}", 
                xid, userId, amount, e);
            return false;
        }
    }
    
    /**
     * Confirm阶段 - 确认扣款
     */
    public boolean confirmDeduct(BusinessActionContext context) {
        String xid = context.getXid();
        Long userId = (Long) context.getActionContext("userId");
        BigDecimal amount = (BigDecimal) context.getActionContext("amount");
        
        log.info("TCC Confirm阶段 - 确认扣款: xid={}, userId={}, amount={}", 
            xid, userId, amount);
        
        try {
            // 1. 查找冻结记录
            AccountFreeze freeze = freezeRepository.findByXid(xid);
            if (freeze == null) {
                log.warn("冻结记录不存在: xid={}", xid);
                return true; // 幂等性处理
            }
            
            if (freeze.getStatus() == FreezeStatus.CONFIRMED) {
                log.warn("重复确认: xid={}", xid);
                return true; // 幂等性处理
            }
            
            // 2. 确认扣款
            freeze.setStatus(FreezeStatus.CONFIRMED);
            freeze.setUpdateTime(LocalDateTime.now());
            freezeRepository.save(freeze);
            
            // 3. 减少冻结金额
            Account account = accountRepository.findByUserId(userId);
            account.setFrozenAmount(account.getFrozenAmount().subtract(amount));
            accountRepository.save(account);
            
            log.info("扣款确认完成: xid={}, userId={}, amount={}", 
                xid, userId, amount);
            return true;
            
        } catch (Exception e) {
            log.error("扣款确认失败: xid={}, userId={}, amount={}", 
                xid, userId, amount, e);
            return false;
        }
    }
    
    /**
     * Cancel阶段 - 取消扣款
     */
    public boolean cancelDeduct(BusinessActionContext context) {
        String xid = context.getXid();
        Long userId = (Long) context.getActionContext("userId");
        BigDecimal amount = (BigDecimal) context.getActionContext("amount");
        
        log.info("TCC Cancel阶段 - 取消扣款: xid={}, userId={}, amount={}", 
            xid, userId, amount);
        
        try {
            // 1. 查找冻结记录
            AccountFreeze freeze = freezeRepository.findByXid(xid);
            if (freeze == null) {
                log.warn("冻结记录不存在: xid={}", xid);
                return true; // 幂等性处理
            }
            
            if (freeze.getStatus() == FreezeStatus.CANCELLED) {
                log.warn("重复取消: xid={}", xid);
                return true; // 幂等性处理
            }
            
            // 2. 取消冻结
            freeze.setStatus(FreezeStatus.CANCELLED);
            freeze.setUpdateTime(LocalDateTime.now());
            freezeRepository.save(freeze);
            
            // 3. 恢复资金
            Account account = accountRepository.findByUserId(userId);
            account.setBalance(account.getBalance().add(amount));
            account.setFrozenAmount(account.getFrozenAmount().subtract(amount));
            accountRepository.save(account);
            
            log.info("扣款取消完成: xid={}, userId={}, amount={}", 
                xid, userId, amount);
            return true;
            
        } catch (Exception e) {
            log.error("扣款取消失败: xid={}, userId={}, amount={}", 
                xid, userId, amount, e);
            return false;
        }
    }
}

/**
 * Saga模式 - 状态机编排
 */
@Component
@Slf4j
public class OrderSagaService {
    
    @Autowired
    private StateMachineEngine stateMachineEngine;
    
    /**
     * 执行订单处理Saga
     */
    public void processOrderSaga(CreateOrderRequest request) {
        log.info("开始执行订单Saga: userId={}", request.getUserId());
        
        try {
            // 创建状态机实例
            StateMachineInstance instance = stateMachineEngine.startAsync(
                "orderProcessSaga",
                UUID.randomUUID().toString(),
                createSagaContext(request)
            );
            
            log.info("订单Saga启动成功: instanceId={}", instance.getId());
            
        } catch (Exception e) {
            log.error("订单Saga启动失败: userId={}", request.getUserId(), e);
            throw new SagaException("Saga执行失败: " + e.getMessage(), e);
        }
    }
    
    private Map<String, Object> createSagaContext(CreateOrderRequest request) {
        Map<String, Object> context = new HashMap<>();
        context.put("userId", request.getUserId());
        context.put("productId", request.getProductId());
        context.put("quantity", request.getQuantity());
        context.put("amount", request.getAmount());
        context.put("orderId", null); // 将在状态流转中设置
        return context;
    }
    
    /**
     * Saga状态定义
     */
    @SagaOrchestrationStart
    public void startOrderProcess(SagaTransactionContext context) {
        log.info("Saga开始 - 订单处理: userId={}", 
            context.getVariable("userId"));
    }
    
    @SagaOrchestrationTask("createOrder")
    public void createOrder(SagaTransactionContext context) {
        log.info("Saga步骤1 - 创建订单");
        
        // 创建订单逻辑
        Order order = orderService.createOrderLocal(
            (Long) context.getVariable("userId"),
            (Long) context.getVariable("productId"),
            (Integer) context.getVariable("quantity"),
            (BigDecimal) context.getVariable("amount")
        );
        
        context.setVariable("orderId", order.getId());
        log.info("订单创建成功: orderId={}", order.getId());
    }
    
    @SagaOrchestrationTask("deductBalance")
    public void deductBalance(SagaTransactionContext context) {
        log.info("Saga步骤2 - 扣减余额");
        
        accountService.deductBalanceLocal(
            (Long) context.getVariable("userId"),
            (BigDecimal) context.getVariable("amount")
        );
        
        log.info("余额扣减成功");
    }
    
    @SagaOrchestrationTask("reduceStock")
    public void reduceStock(SagaTransactionContext context) {
        log.info("Saga步骤3 - 扣减库存");
        
        productService.reduceStockLocal(
            (Long) context.getVariable("productId"),
            (Integer) context.getVariable("quantity")
        );
        
        log.info("库存扣减成功");
    }
    
    @SagaOrchestrationTask("updateOrderStatus")
    public void updateOrderStatus(SagaTransactionContext context) {
        log.info("Saga步骤4 - 更新订单状态");
        
        orderService.updateOrderStatusLocal(
            (Long) context.getVariable("orderId"),
            OrderStatus.SUCCESS
        );
        
        log.info("订单状态更新成功");
    }
    
    // 补偿方法
    @SagaOrchestrationCompensation("createOrder")
    public void compensateCreateOrder(SagaTransactionContext context) {
        log.info("Saga补偿 - 取消订单");
        
        Long orderId = (Long) context.getVariable("orderId");
        if (orderId != null) {
            orderService.cancelOrderLocal(orderId);
            log.info("订单取消完成: orderId={}", orderId);
        }
    }
    
    @SagaOrchestrationCompensation("deductBalance")
    public void compensateDeductBalance(SagaTransactionContext context) {
        log.info("Saga补偿 - 恢复余额");
        
        accountService.refundBalanceLocal(
            (Long) context.getVariable("userId"),
            (BigDecimal) context.getVariable("amount")
        );
        
        log.info("余额恢复完成");
    }
    
    @SagaOrchestrationCompensation("reduceStock")
    public void compensateReduceStock(SagaTransactionContext context) {
        log.info("Saga补偿 - 恢复库存");
        
        productService.restoreStockLocal(
            (Long) context.getVariable("productId"),
            (Integer) context.getVariable("quantity")
        );
        
        log.info("库存恢复完成");
    }
}

🎯 面试重点总结

💡 分布式事务架构师面试题

1. 事务模式选择

Q: 什么场景选择TCC?什么场景选择Saga?
A:

  • TCC适用场景:资金交易、库存扣减等需要强一致性的核心业务
  • Saga适用场景:订单流程、批处理等长事务业务流程
  • 选择依据:一致性要求、业务复杂度、性能要求
2. 分布式事务设计

Q: 如何设计一个高可用的分布式事务系统?
A:

  • 幂等性设计:防重试、防重复提交
  • 补偿机制:业务补偿、技术补偿
  • 监控告警:事务状态监控、异常告警
  • 容错处理:超时重试、人工介入
3. 性能优化

Q: 分布式事务性能优化策略?
A:

  • 异步处理:非关键步骤异步执行
  • 批量操作:减少网络开销
  • 缓存优化:减少数据库访问
  • 分片策略:避免热点数据

🎖️ 分布式事务架构师核心能力

  1. 方案选型能力:根据业务特点选择合适的事务模式
  2. 系统设计能力:设计高可用、高性能的事务系统
  3. 问题诊断能力:快速定位和解决分布式事务问题
  4. 优化调优能力:持续优化事务系统性能

🔄 分布式事务是分布式系统的核心挑战!掌握技术选型与实现原理,构建高可靠的分布式事务系统!


📌 行动指南

  1. 点赞 → 让更多Java开发者掌握分布式技术
  2. 评论 → 留言"分布式技术"领取[分布式系统设计模板]
  3. 关注 → 追踪更新《更多Java技术精彩内容》(已写完待发布)
  4. 赞赏 → 解锁完整源码+专属技术咨询

🚀 下期预告

《更多Java技术精彩内容》关注可抢先看

📚 相关推荐

让我们一起在Java的世界里探索更多精彩内容! 🚀

相关推荐
我重来不说话2 小时前
xFile:高性能虚拟分布式加密存储系统——Go
分布式·压缩存储·权限系统·动态加密·虚拟存储
2401_831501733 小时前
Linux之Zabbix分布式监控篇(一)
分布式·zabbix
gorgor在码农4 小时前
分布式ID方案
分布式
Aikes9025 小时前
基于redis的分布式session共享管理之销毁事件不生效问题
redis·分布式·缓存
简婷187019987757 小时前
高速路上的 “阳光哨兵”:分布式光伏监控系统守护能源高效运转
分布式·能源
帅次8 小时前
系统分析师-计算机系统-输入输出系统
人工智能·分布式·深度学习·神经网络·架构·系统架构·硬件架构
钺商科技12 小时前
【6.1.3 漫画分布式锁】
分布式
Bug退退退1231 天前
RabbitMQ 之消息积压
分布式·rabbitmq
熊猫钓鱼>_>1 天前
Hadoop 用户入门指南:驾驭大数据的力量
大数据·hadoop·分布式