
事务回查涉及多个时间参数合理配置这些参数是事务消息稳定运行的关键参数 默认值 说明 配置位置transactionTimeout 6000ms 本地事务执行超时时间。超过这个时间Broker 认为事务状态未知触发回查 Producer 端transactionCheckInterval 60000ms Broker 回查半消息的间隔 Broker 端transactionCheckMax 15 次 最大回查次数。超过后默认回滚 Broker 端Broker 端配置transactionCheckInterval60000 # 回查间隔 60 秒transactionCheckMax15 # 最大回查 15 次transactionCheckTimeout6000 # 回查请求超时时间 6 秒Producer 端配置DefaultMQProducer producer new DefaultMQProducer();producer.setTransactionTimeout(6000); // 事务超时 6 秒配置建议transactionTimeout 要根据业务调整如果本地事务涉及多个数据库操作或远程调用需要设置足够的超时时间transactionCheckInterval 不宜过短频繁回查会增加 Broker 和 Producer 的负载transactionCheckMax 要结合业务容忍度核心业务可以设置更大的值如 30 次给系统更长的恢复时间事务消息的使用限制与注意事项事务消息虽强但并非万能。在使用时有几条重要的限制需要牢记限制一不支持延迟消息和批量消息事务消息不能和延迟消息、批量消息组合使用。事务消息本身就是“先存后发”的机制和延迟消息的“定时投递”在逻辑上冲突。限制二Consumer 必须处理重复消费事务消息虽然保证了“事务提交后消息可见”但在异常情况下如网络重传、RebalanceConsumer 仍然可能重复消费消息。业务方必须做好幂等处理。限制三事务消息的发送是同步的事务消息只支持同步发送不支持异步或单向发送。因为需要等待本地事务执行结果同步是最自然的模式。限制四事务消息不支持广播消费广播消费模式下每个 Consumer 独立消费事务消息的状态管理会变得复杂所以 RocketMQ 的事务消息不支持广播模式。限制五半消息对 Broker 有存储开销每条半消息在 COMMIT 或 ROLLBACK 之前都会占用 Broker 的存储空间CommitLog 和 ConsumeQueue。如果有大量半消息长时间 UNKNOWN会导致存储膨胀。使用限制❌ 不支持延迟消息❌ 不支持批量消息❌ 不支持异步/单向发送❌ 不支持广播消费⚠️ 半消息占用存储空间事务消息回查失败的处理策略回查不是万能的它也可能失败。我们需要理解各种失败场景及应对策略场景一Producer 节点宕机如果所有 Producer 节点都宕机了Broker 的回查请求无法送达。→ 策略配置 transactionCheckMax 和 transactionCheckInterval在 Producer 恢复前Broker 会持续尝试回查。如果超过最大次数仍无响应Broker 默认回滚。运维层面需要监控“超时未确认”的半消息数量。场景二回查请求超时Producer 收到了回查请求但因为网络或负载原因响应超时。→ 策略Broker 会重试回查下一次扫描时再次发起。Producer 端应确保 checkLocalTransaction() 方法的执行时间远小于 transactionCheckTimeout。场景三checkLocalTransaction 返回 UNKNOWNProducer 仍然无法确定事务状态比如依赖的数据库暂时不可用。→ 策略返回 UNKNOWN 后Broker 会在下一个回查周期再次询问。建议在业务层实现重试机制直到能确定状态为止。场景四超过最大回查次数15 次回查都失败了消息仍然 UNKNOWN。→ 策略Broker 默认回滚消息从 5.x 开始可以通过配置修改默认行为。运维需要监控这类情况手动介入处理。Producer 宕机响应超时返回 UNKNOWN超过最大次数回查失败失败类型等待 Producer 恢复Broker 持续重试超限后默认回滚优化网络或缩短 checkLocalTransaction 耗时优化业务检查逻辑确保能快速确定状态监控告警人工介入排查Done事务消息与分布式事务的对比TCC、Saga事务消息只是分布式事务的一种解决方案。我们来对比一下主流的几种方案TCCTry-Confirm-Cancel维度 TCC 事务消息核心思想 预留资源 → 确认/取消 半消息 → 提交/回滚业务侵入 高需要实现 Try/Confirm/Cancel 中只需实现本地事务 回查数据一致性 强一致性 最终一致性适用场景 跨服务调用、资源预留 消息驱动的异步场景性能 较低多次 RPC 较高一次半消息 本地事务Saga维度 Saga 事务消息核心思想 长事务拆分为多个本地事务 补偿 本地事务 消息最终一致性业务侵入 高需要实现正向操作 补偿操作 中数据一致性 最终一致性 最终一致性适用场景 长事务、跨多个服务的复杂流程 消息驱动的异步解耦场景对比总结选型建议分布式事务方案对比TCC强一致性业务侵入高Saga最终一致性需要补偿事务消息最终一致性通过回查自愈 事务消息消息驱动、异步解耦、对一致性要求不是强同步 TCC跨服务调用、需要强一致性、资源可预留 Saga长事务、复杂流程、需要有补偿逻辑选型建议事务消息适合消息驱动的异步场景对性能要求高能接受最终一致性TCC 适合跨服务调用的强一致性场景资源可以预留如扣减库存、冻结资金Saga 适合复杂的长事务流程每个步骤都有明确的补偿操作事务消息与普通消息的性能对比事务消息因为多了“半消息 本地事务 可能的回查”这些步骤性能自然不如普通消息。我们来量化对比一下对比维度 普通消息 事务消息 性能差距网络往返 1 次发送 2-3 次发送半消息 提交/回滚 可能的回查 约 2 倍延迟Broker 写入 1 次 CommitLog 写入 2 次 CommitLog 写入半消息 提交标记 约 2 倍存储 IO存储空间 消息体 消息体 事务状态记录 约额外 30%-50%CPU 开销 低 中需要事务状态管理和扫描 约 20%-30% 额外TPS 上限 ~10 万级 ~2-3 万级 约为普通消息的 1/3 - 1/5事务消息发送发送半消息写入半消息返回 ACK执行本地事务发送 COMMIT/ROLLBACK标记消息状态返回 ACK2 次网络往返 2 次写入本地事务 可能的回查普通消息发送发送请求写入 CommitLog返回 ACK1 次网络往返 1 次写入性能损耗的核心来源半消息额外写入每条事务消息至少多一次 CommitLog 写入事务状态维护Broker 需要维护和扫描半消息的状态网络往返增加从 1 次变成 2 次半消息 提交/回滚回查开销如果返回 UNKNOWN还有额外的回查负载 小贴士如果你的业务不需要强一致性保障普通消息 幂等消费可能是更好的选择。事务消息虽好但不要滥用——它只应该在“本地事务和消息发送必须保持一致”的场景下使用。事务消息的内部存储结构了解事务消息的存储细节能帮你更深入地理解它的工作原理事务消息存储结构回滚后标记为已删除不影响 CommitLog消息不可消费提交后在原 ConsumeQueue 位置标记为可见可能增加 Op 消息记录提交操作