漫画分布式事务技术选型
🎯 学习目标:掌握架构师核心技能——分布式事务技术选型与一致性解决方案,构建高可靠的分布式系统
🎭 第一章:分布式事务模式对比
🤔 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架构与模式
// 🛠️ Seata分布式事务实战/*** Seata配置中心*/
@Configuration
@EnableAutoDataSourceProxy
public class SeataConfig {/*** AT模式数据源代理*/@Bean@Primarypublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}/*** TCC模式业务资源管理器*/@Beanpublic TccTransactionManager tccTransactionManager() {return new TccTransactionManager();}/*** Saga状态机配置*/@Beanpublic StateMachineEngine stateMachineEngine() {StateMachineEngineBuilder builder = StateMachineEngineBuilder.newBuilder();builder.setDataSource(dataSource()).setTransactionManager(platformTransactionManager()).setApplicationContext(applicationContext);return builder.build();}
}/*** AT模式 - 自动补偿*/
@Service
@Slf4j
public class OrderServiceAT {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate AccountServiceClient accountServiceClient;@Autowiredprivate 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 {@Autowiredprivate AccountRepository accountRepository;@Autowiredprivate 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 {@Autowiredprivate 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状态定义*/@SagaOrchestrationStartpublic 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:
- 异步处理:非关键步骤异步执行
- 批量操作:减少网络开销
- 缓存优化:减少数据库访问
- 分片策略:避免热点数据
🎖️ 分布式事务架构师核心能力
- 方案选型能力:根据业务特点选择合适的事务模式
- 系统设计能力:设计高可用、高性能的事务系统
- 问题诊断能力:快速定位和解决分布式事务问题
- 优化调优能力:持续优化事务系统性能
🔄 分布式事务是分布式系统的核心挑战!掌握技术选型与实现原理,构建高可靠的分布式事务系统!
📌 行动指南
- 点赞 → 让更多Java开发者掌握分布式技术
- 评论 → 留言"分布式技术"领取[分布式系统设计模板]
- 关注 → 追踪更新《更多Java技术精彩内容》(已写完待发布)
- 赞赏 → 解锁完整源码+专属技术咨询
🚀 下期预告
《更多Java技术精彩内容》关注可抢先看
📚 相关推荐:
- 漫画Java基础
- 漫画Spring全家桶
- 漫画JVM调优
让我们一起在Java的世界里探索更多精彩内容! 🚀