题目:如何基于 MQ 实现分布式事务
难度:medium
标签:arch/distributed/transaction, mq/transactional, difficulty/medium
评分:⭐⭐☆☆☆(2/5)
首先这个题目上可能有一点误区。常规来说,分布式事务并不一定要基于 MQ,如果非要使用 MQ 去实现分布式事务的话,资源有些浪费。毕竟分布式事务是常态,但是都有 MQ 不一定。
分支事务,首先你要识别当前事务的设置,然后要保证几个服务之间的事务的统一,也就是说几个服务之间的工作的一致性,大家成功了就都成功,失败了就都失败。
这时涉及几个点,一个是要触发大家的感知大家的工作内容,比如说大家都工作成功了,或者大家某个工作成功,某个工作失败。如果某人工作失败,这时候需要回滚,大家都成功了才往下继续进行。其中回滚侧就可以通过 MQ 去实现。当出现任务失败的时候,把消息,失败的消息发到 MQ 中,然后异步的去进行业务的反向回滚,把所有的已经执行完的操作进行回滚。
但常规的一般不是这么实现的,当然这么实现也可以。
优点:
不足:
补充:
BEGIN → INSERT outbox_msg → 业务写入 → COMMIT;后台定时任务扫 outbox 表投递 MQTransactionProducer.send + TransactionListener 回查机制,防止 Producer 崩溃导致半消息悬挂核心考点定位:考察对 MQ 在分布式事务中角色的理解,以及主流落地方案(事务消息 / 本地消息表 / 可靠消息 + 幂等)的实现细节。
知识点拆解:
BEGIN → INSERT 业务数据 + INSERT outbox_msg → COMMITKafkaTransaction,跨 topic 原子读写enable.idempotence=true)+ 事务 Producer + 隔离级别 read_committed递进:本质问题 → MQ 角色 → 四种方案 → 共同约束 → 工程实践
考察方向:
延伸递进面试题:
checkLocalTransaction 接口面试官您好,基于 MQ 实现分布式事务的核心思路是:用消息作为跨服务的通信桥梁,把强一致的同步协调转为最终一致的异步传播。业界主流有三种方案,我分别说下。
第一种是事务消息,以 RocketMQ 最典型。Producer 发送的是"半消息",这条消息对 Consumer 不可见;然后 Producer 执行本地事务,成功后向 Broker 提交,消息变成对 Consumer 可见;如果本地事务失败,就回滚半消息。这里有个关键设计——如果 Producer 在事务提交前崩溃了,MQ Broker 会定时回查 Producer 的本地事务状态(通过 checkLocalTransaction 接口),Producer 根据自己库里是否有该笔业务记录返回 COMMIT、ROLLBACK 或 UNKNOWN,防止半消息悬挂。这个方案最大的好处是消息和业务的强绑定,缺点是依赖 RocketMQ 的事务特性。
第二种是本地消息表,也叫 Outbox 模式。业务库里新增一张 outbox 表,业务操作在本地事务里同时写入业务表和 outbox 表:BEGIN → INSERT 订单 + INSERT outbox_msg → COMMIT。这样"业务写入"和"消息待发"是本地事务的原子操作。后台用定时任务或 Canal 监听 binlog,扫 outbox 表把消息投递到 MQ,投递成功后删除或标记 outbox。这个方案的优势是不依赖 MQ 的事务特性,Kafka、RabbitMQ 都能用;缺点是需要额外维护定时任务和 Outbox 表。
第三种是可靠消息 + 幂等消费。Producer 保证消息可靠投递(acks=all、重试),Consumer 用业务唯一键(比如订单号、支付流水号)做幂等去重。这种方案最简单但最弱——只保证消息最终送达,不保证业务与消息的原子性,比如可能业务提交成功了但消息在投递过程中丢失。
不管用哪种方案,有两个共同约束:第一消费端必须幂等,因为 MQ 是"至少投递一次",可能重复消费;第二要有对账兜底机制,定时扫描未完成的业务状态做补偿。
关于强一致 vs 最终一致:MQ 方案实现的是最终一致,消费端可能出现"上游已提交、下游还没消费"的时间窗口,通常是秒级到分钟级。真正的强一致(比如金融账务的原子扣款)还是需要同步协调的 2PC/XA/Seata AT,代价是高延迟和低吞吐。
在具体工程里,电商下单这种典型场景的做法是:库存服务本地事务扣库存 → 通过本地消息表 or 事务消息发出"扣库存成功"消息 → 订单服务消费消息创建订单(消费端用订单号做幂等)→ 支付服务消费消息发起支付。这样即使消息延迟,也不会重复扣库存,也不会重复下单。
另外 Kafka 2.5+ 也提供了原生事务 API(KafkaTransaction),跨 topic 事务性读写 + 幂等 Producer,也是类似的思路。选型看业务对一致性的要求:金融选本地消息表 + Seata AT 兜底,互联网选事务消息够用了。
题目:如何基于 MQ 实现分布式事务
难度:medium
标签:arch/distributed/transaction, mq/transactional, difficulty/medium
评分:⭐⭐⭐☆☆(3/5)
练习次数:2
基于 mq 实现的分布式事务稳定的是最终一致性事务;
常见的有两个一个是基于 rocket mq 的半消息实现的事务,先执行执行后发送半消息,执行成功了对应的消费方才能看到消息,否则这个半消息就直接不可见了;
还可以基于本地事务表,然后发送 mq 消息,进行对应更新,来实现事务变更记录以及不同服务间事务的执行;
优点:
不足:
补充:
ℹ️ 完整讲解见上方首次记录(2026-10-10)