RocketMQ的分布式事务消息

📅 2026/8/25 5:53:15
RocketMQ的分布式事务消息
RocketMQ分布式事务消息的核心目标是实现本地事务与消息发送的最终一致性。本地数据库执行事务同时要发送消息希望做到本地事务成功则消息一定发出本地事务回滚则消息不发出。RocketMQ 事务消息不能做到强一致是最终一致性方案。整体流程半消息机制四个核心阶段发送半消息 → 执行本地事务 → 提交 / 回滚半消息 → 事务回查1、发送半消息Half MessageProducer 向 Broker 发送事务半消息。消息已经存储在 Broker但是对消费者不可见消费者无法消费这条消息。Broker 返回 OK半消息落库成功。2、执行本地事务Producer 收到半消息成功响应后执行业务本地数据库事务新增订单、扣减库存等。本地事务执行完成得到三种状态LocalTransactionState.COMMIT_MESSAGE本地事务成功 → 通知 Broker提交半消息消息对外可见消费者可以消费。LocalTransactionState.ROLLBACK_MESSAGE本地事务失败 → 通知 Broker回滚半消息直接删除消息消费者永远收不到。LocalTransactionState.UNKNOW状态未知网络抖动、Producer 宕机Broker 不知道本地事务结果等待事务回查。3、Broker 处理提交 / 回滚COMMIT半消息转为普通消息投递给 Consumer。ROLLBACK直接删除这条半消息。4、事务回查checkLocalTransaction当 Producer 没有给 Broker 返回 commit/rollback进程崩溃、网络异常Broker 会定时发起事务回查询问 Producer你这条半消息对应的本地事务到底成功还是失败Broker 周期性回查默认回查次数 15 次间隔可配置Producer 实现checkLocalTransaction接口查询数据库本地事务状态返回 COMMIT / ROLLBACK / UNKNOW如果多次回查都返回 UNKNOWBroker 回滚删除半消息。若本地事务超过回查次数半消息被删除后续本地事务执行成功不会再产生新的半事务消息会造成数据不一致。注意1、半消息不会被消费者消费只有收到 commit 之后消息才对外可见。2、回查逻辑必须可靠checkLocalTransaction必须查询数据库真实业务状态不能存内存状态。 如果 Producer 宕机重启内存状态丢失回查只能靠查 DB。3、本地事务和半消息发送不是原子半消息发送成功后本地事务依然有可能执行失败此时返回 rollback 删除消息。4、事务消息只保证本地事务结果 和 消息投递 最终一致本地事务成功 → 消息一定会投递At‑Least‑Once消息仍然可能重复消费本地事务失败 → 消息一定不会投递。消费者这边依旧存在重复消费消费端依旧要做幂等。消费端若是消费失败只会走普通消息消费流程消费失败添加进重试队列重试失败添加到死信队列RocketMQ不会主动提醒生产者回滚。如何保证分布式事务最终一致性事务消息只保证本地事务结果 和 消息投递 最终一致整个事务是否最终一致需要用户自行保证1、消息需要做幂等消费消息投递本来就有可能重复如网络原因导致确认消息未正常接收消息消费失败会被添加到重试队列都有可能导致消息重复。2、添加死信队列监听监听死信 Topic消息进入死信后调用上游生产者接口业务层面做逆向补偿手动写代码回滚订单取消订单。3、状态机设计上游 DB 不要直接完成最终状态。例订单创建状态为待确认下游消费成功之后下游回发一条消息给订单服务订单收到消息才把订单更新为已确认。下游消费失败订单一直处于待确认状态定时任务扫描待确认超时订单做关闭。