在微服务架构与分布式系统盛行的今天数据一致性问题成为开发者必须直面的核心挑战。传统的本地事务ACID在跨服务、跨数据库的场景下显得力不从心分布式事务应运而生。本文将从实战角度出发深入剖析6种主流的分布式事务解决方案并附上可运行的代码示例助你根据业务场景精准选型。### 1. 两阶段提交2PC/XA原理引入全局事务管理器TM分两阶段协调多个资源管理器RM。阶段一TM询问所有RM是否可提交阶段二若全部同意则全局提交否则全局回滚。优点强一致性实现简单。缺点存在同步阻塞协调者单点极端情况下可能阻塞如协调者宕机。适用场景对一致性要求极高、并发量低的内部系统。代码示例Java JTAjavaimport javax.transaction.UserTransaction;import javax.naming.InitialContext;public class TwoPhaseCommitDemo { public void transfer() throws Exception { InitialContext ctx new InitialContext(); UserTransaction utx (UserTransaction) ctx.lookup(java:comp/UserTransaction); try { utx.begin(); // 操作数据库A jdbcA.execute(UPDATE account SET balance balance - 100 WHERE id 1); // 操作数据库B jdbcB.execute(UPDATE account SET balance balance 100 WHERE id 2); utx.commit(); // 全局提交 } catch (Exception e) { utx.rollback(); // 全局回滚 throw e; } }}### 2. 三阶段提交3PC原理在2PC基础上引入“准备提交”阶段CanCommit, PreCommit, DoCommit增加超时机制降低阻塞风险。优点解决协调者故障导致的阻塞问题。缺点实现复杂极端情况仍无法保证完全一致性。适用场景对2PC阻塞敏感但可容忍少量不一致的分布式系统。代码示例伪代码python# 三阶段提交状态机示意class ThreePhaseCommit: def can_commit(self, participants): for p in participants: if not p.prepare(): return False return True def pre_commit(self, participants): for p in participants: p.pre_commit() # 写入undo日志 def do_commit(self, participants): for p in participants: p.commit() # 最终提交### 3. 本地消息表异步确保原理核心思路是“最终一致性”。在业务操作所在的数据库中创建消息表将业务操作与写消息表放在同一个本地事务中然后通过定时任务或消息队列将消息发送给下游服务下游消费成功后回调确认。优点无强依赖性能较好可靠性高。缺点需要额外维护消息表存在消息重复消费问题需幂等。适用场景订单系统、支付系统等对一致性要求中等、性能要求高的场景。代码示例Spring MyBatisjavaTransactionalpublic void createOrder(Order order) { // 1. 插入订单表本地事务 orderMapper.insert(order); // 2. 插入消息表同一本地事务 MessageRecord msg new MessageRecord(); msg.setMsgId(UUID.randomUUID().toString()); msg.setContent(JSON.toJSONString(order)); msg.setStatus(pending); messageMapper.insert(msg); // 3. 事务提交后定时任务扫描消息表发送MQ}Scheduled(cron 0/5 * * * * ?)public void sendMessage() { ListMessageRecord pendingList messageMapper.selectPending(); for (MessageRecord record : pendingList) { try { mqTemplate.send(order_topic, record.getContent()); record.setStatus(sent); messageMapper.update(record); } catch (Exception e) { // 重试或告警 } }}### 4. 事务消息RocketMQ原理利用消息队列的事务消息特性。发送方先发送“半消息”对消费者不可见然后执行本地事务根据结果提交或回滚半消息。消息队列在超时后主动回查事务状态。优点解耦性强无需额外消息表可靠性高。缺点依赖特定MQ如RocketMQ对回查接口有要求。适用场景电商下单、库存扣减等异步解耦场景。代码示例RocketMQjava// 发送事务消息TransactionMQProducer producer new TransactionMQProducer(tx_producer);producer.setTransactionListener(new TransactionListener() { Override public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { try { // 执行本地业务如扣减库存 orderService.createOrder(arg); return LocalTransactionState.COMMIT_MESSAGE; } catch (Exception e) { return LocalTransactionState.ROLLBACK_MESSAGE; } } Override public LocalTransactionState checkLocalTransaction(MessageExt msg) { // 回查本地事务状态 String orderId msg.getKeys(); return orderService.isOrderExists(orderId) ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.ROLLBACK_MESSAGE; }});// 发送半消息Message msg new Message(order_topic, order, orderId, orderInfo.getBytes());SendResult sendResult producer.sendMessageInTransaction(msg, orderInfo);### 5. TCCTry-Confirm-Cancel原理业务层面拆分为三个操作Try预留资源、Confirm确认执行、Cancel回滚释放。每个参与方实现这三个接口由协调者统一调度。优点无阻塞性能高灵活性好。缺点业务侵入性强需要编写大量补偿逻辑实现复杂。适用场景资金类操作转账、支付、票务预订等需要强资源控制的场景。代码示例Java 接口定义javapublic interface TccAction { // 预留资源如冻结余额 boolean try() throws Exception; // 确认执行扣减冻结金额 boolean confirm() throws Exception; // 取消解冻余额 boolean cancel() throws Exception;}// 协调器伪代码public class TccCoordinator { public void doTcc(ListTccAction actions) { // Try阶段 for (TccAction action : actions) { if (!action.try()) { // 执行Cancel for (int i actions.size()-1; i 0; i--) { actions.get(i).cancel(); } return; } } // Confirm阶段 for (TccAction action : actions) { action.confirm(); } }}### 6. Saga 模式原理将长事务拆分为一系列本地事务每个事务有对应的补偿操作。若某一步失败则依次调用之前的补偿操作回滚。优点无阻塞适合长事务性能较好。缺点隔离性弱事务间未提交的数据不可见需要设计补偿操作。适用场景旅游预订订机票酒店、订单聚合等跨服务多步骤流程。代码示例Spring Boot Sagajava// 定义Saga步骤Componentpublic class SagaOrderFlow { Autowired private OrderService orderService; Autowired private InventoryService inventoryService; Autowired private PaymentService paymentService; // 主流程 public void createOrderSaga() { try { Long orderId orderService.createOrder(); // 步骤1 inventoryService.deductStock(orderId); // 步骤2 paymentService.pay(orderId); // 步骤3 } catch (Exception e) { // 补偿反向调用 paymentService.refund(orderId); inventoryService.addStock(orderId); orderService.cancelOrder(orderId); } }}### 总结分布式事务没有“银弹”每种方案都有其特定的适用场景与代价-强一致性优先选择2PC/3PC但需接受性能与可用性折损。-最终一致性优先本地消息表、事务消息、Saga是常见选择其中事务消息最优雅Saga适合长事务。-资源控制需求TCC虽复杂但对资金类操作最为安全。实际开发中建议先明确业务对一致性的容忍度、吞吐量要求以及团队技术栈再做出选型。同时务必考虑幂等设计、重试机制与监控告警以确保系统的鲁棒性。分布式事务的实践是架构师必修课希望本文能为你在技术决策中提供有价值的参考。