【架构实战】分布式事务解决方案
一、分布式事务的挑战在微服务架构下一个业务操作可能涉及多个服务的数据修改。传统的本地事务无法保证跨服务的数据一致性。经典场景用户下单 → 订单服务扣库存 → 支付服务扣余额 → 物流服务创建运单 任何一步失败都需要回滚之前的操作二、CAP定理回顾C一致性所有节点数据一致A可用性每个请求都能得到响应P分区容错网络分区时系统仍能工作三者只能满足其二分布式系统必须选择CP或AP。三、主流解决方案方案12PC两阶段提交阶段1Prepare准备 协调者 → 所有参与者准备提交 参与者 → 协调者准备就绪 ✓/✗ 阶段2Commit/Rollback提交/回滚 全部就绪 → Commit 任一失败 → Rollback优点强一致性缺点同步阻塞性能差单点故障方案2TCCTry-Confirm-Cancel// Try预留资源publicbooleantryDeduct(StringuserId,BigDecimalamount){AccountaccountaccountMapper.selectById(userId);if(account.getFrozen().add(amount).compareTo(account.getBalance())0){returnfalse;}accountMapper.freeze(userId,amount);returntrue;}// Confirm确认提交publicvoidconfirmDeduct(StringuserId,BigDecimalamount){accountMapper.deduct(userId,amount);}// Cancel取消回滚publicvoidcancelDeduct(StringuserId,BigDecimalamount){accountMapper.unfreeze(userId,amount);}优点性能好无锁缺点业务侵入性强需实现三个接口方案3Saga模式T1 → T2 → T3 → T4 ↓ ↓ ↓ ↓ C1 ← C2 ← C3 ← C4 (补偿操作) 正向操作链 补偿操作链// Saga编排器publicclassOrderSaga{publicvoidexecute(Orderorder){try{orderService.create(order);inventoryService.deduct(order);paymentService.pay(order);shippingService.create(order);}catch(Exceptione){// 按相反顺序补偿shippingService.cancel(order);paymentService.refund(order);inventoryService.restore(order);orderService.cancel(order);}}}方案4可靠消息最终一致性// 本地消息表TransactionalpublicvoidcreateOrder(Orderorder){orderMapper.insert(order);// 同一事务中写入本地消息表localMessageMapper.insert(newLocalMessage(order.getId(),ORDER_CREATED,order.toString()));}// 定时任务扫描消息表投递到MQScheduled(fixedRate5000)publicvoidscanAndSend(){ListmessageslocalMessageMapper.selectUnsentList();for(LocalMessagemsg:messages){try{mqTemplate.send(msg.getTopic(),msg.getContent());msg.setStatus(SENT);localMessageMapper.updateById(msg);}catch(Exceptione){log.error(消息投递失败,e);}}}四、Seata框架实战# Seata Server配置seata:enabled:trueapplication-id:order-servicetx-service-group:my_tx_groupservice:vgroup-mapping:my_tx_group:defaultregistry:type:nacosnacos:server-addr:127.0.0.1:8848// 使用GlobalTransactional注解ServicepublicclassOrderService{AutowiredprivateInventoryClientinventoryClient;AutowiredprivatePaymentClientpaymentClient;GlobalTransactional(namecreate-order,timeoutMills30000)publicOrdercreateOrder(OrderRequestrequest){// 1. 创建订单OrderorderorderMapper.insert(request);// 2. 扣减库存远程调用inventoryClient.deduct(request.getProductId(),request.getQuantity());// 3. 创建支付单远程调用paymentClient.create(order.getId(),request.getAmount());returnorder;}}五、方案对比与选型方案一致性性能复杂度适用场景2PC强一致低中传统数据库TCC最终一致高高资金类业务Saga最终一致高中长流程业务可靠消息最终一致高低异步场景选型建议强一致性要求TCC最终一致性可接受Saga 或 可靠消息简单场景本地消息表对性能要求高Saga六、常见问题Q1空回滚怎么办A记录事务状态执行Cancel前检查是否已执行TryQ2悬挂问题A通过全局事务ID关联保证幂等性Q3补偿操作也失败了A引入重试机制 人工干预兜底七、总结分布式事务没有银弹需要根据业务特点选择合适方案核心原则BASE理论基本可用、软状态、最终一致设计思路宁可补偿不可阻塞工程实践幂等性是基础重试是保障思考题你的项目中如何处理分布式事务有没有遇到过数据不一致的问题个人观点仅供参考
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2453090.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!