Rocketmq半消息
背景和价值
RocketMQ 的半消息(Half Message)是一种用于实现分布式事务最终一致性的核心机制,通过两阶段提交(2PC)的优化变体,保障本地事务与消息发送的原子性。其原理、应用方式以及与 Seata AT 模式的整合方案如下:
一、RocketMQ 半消息原理
1. 核心流程(两阶段提交)
- 阶段一:发送半消息
- 生产者发送消息到 Broker,消息被标记为“半消息”(Half Message)。
- Broker 将半消息持久化到特殊 Topic(如
RMQ_SYS_TRANS_HALF_TOPIC),对消费者不可见 。
- 阶段二:提交/回滚
- 本地事务执行:生产者收到半消息确认后,执行本地事务(如创建订单)。
- 二次确认:
- 若本地事务成功 → 向 Broker 发送 Commit,半消息转为可投递状态,存入目标 Topic。
- 若本地事务失败 → 发送 Rollback,Broker 删除半消息。
- 事务回查(容错机制):
- 若 Broker 未收到二次确认(如生产者宕机),会定期向生产者发起回查(默认最多 15 次)。
- 生产者检查本地事务状态,重新提交 Commit/Rollback。
2. 关键设计
- 半消息隔离性:半消息存储与普通消息分离,避免未确认消息被消费。
- 回查机制:解决网络闪断或生产者故障导致的状态丢失问题。
- 最终一致性:仅保证消息发送与本地事务的原子性,不保证消费者一定消费成功(需消费者幂等设计)。
二、应用场景与实战
1. 典型场景
- 电商下单流程:graph LR A[订单服务] -->|1. 发送半消息| B(RocketMQ) A -->|2. 创建订单| C[本地事务] C -->|成功| B(Commit) C -->|失败| B(Rollback) B -->|3. 可投递消息| D[库存服务-消费消息扣库存]
- 订单服务创建订单(本地事务)与发送“扣库存消息”绑定,避免订单成功但消息未发送的脏数据。
2. 代码实现
生产者需使用 TransactionMQProducer 并实现 TransactionListener 接口:
// 发送半消息
TransactionMQProducer producer = new TransactionMQProducer("group_name");
producer.setTransactionListener(new TransactionListener() {
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
boolean success = executeLocalBusiness(); // 执行本地事务
return success ? COMMIT_MESSAGE : ROLLBACK_MESSAGE; // 返回状态
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
TransactionStatus status = queryLocalTxStatus(msg); // 回查本地事务状态
return status == SUCCESS ? COMMIT_MESSAGE : ROLLBACK_MESSAGE;
}
});
producer.sendMessageInTransaction(msg, null); // 发送事务消息

浙公网安备 33010602011771号