消息类型
RocketMQ 的消息按「有没有特殊语义」分成四类:
| 类型 | 一句话 |
|---|---|
| 普通消息 | 无特殊语义,最常用 |
| 顺序消息 | 保证同一队列内按发送顺序消费 |
| 事务消息 | 保证「本地事务 + 发消息」的最终一致性 |
| 延时消息 | 指定延时时间后才投递 |
一、普通消息
是什么:没有特殊语义的消息,最常用的一类。
三种发送方式(重点):
| 发送方式 | 特点 | 适用场景 |
|---|---|---|
同步发送 syncSend |
阻塞等待 Broker 返回结果 | 重要消息,必须确认发出去了 |
异步发送 asyncSend |
不阻塞,通过回调拿结果 | 对响应时间敏感,也要知道结果 |
单向发送 sendOneWay |
发出去就不管,不关心结果 | 日志、埋点这类丢了无所谓的 |
怎么选 :就看你要不要知道发送结果------要就同步 / 异步,不要就单向。
消费模式 :默认是并发消费(多个线程并行处理同一个队列里的消息),不保证顺序。
二、顺序消息
解决什么问题:同一业务实体的多条消息,必须按发送顺序处理。
例子:一个订单的「创建 → 支付 → 发货」,如果消费顺序乱了,会出现「先发货后支付」。
实现原理(生产端和消费端要配合):
| 端 | 做什么 |
|---|---|
| 生产端 | 用 MessageQueueSelector,把同一个业务 Key (如订单 ID)的消息发到同一个 Queue |
| 消费端 | 用 MessageListenerOrderly,对该队列加锁串行消费 |
关键限制 :RocketMQ 只保证「同一个 Queue 内 」有序,不保证全局有序。
两种粒度:
| 粒度 | 做法 | 评价 |
|---|---|---|
| 全局有序 | 一个 Topic 只设一个 Queue | 性能极差,基本不用 |
| 分区有序 | 同一业务 Key 进同一个 Queue | 推荐做法 |
代价 :顺序消费是串行的,并发度下降,吞吐低于并发消费。
三、事务消息
解决什么问题 :让「本地事务 」和「发消息」这两件事要么都成功,要么都不做。
典型场景:下单扣库存成功后要发消息通知积分服务。如果扣完库存、发消息失败,数据就不一致了。
核心机制:半消息(Half Message)
sql
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Producer │ │ Broker │ │ Consumer │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ ① 发送半消息 │ │
│─────────────────────►│ │
│ │ 存入 HALF_TOPIC │
│ ② 返回成功 │ (消费者看不到) │
│◄─────────────────────│ │
│ │ │
│ ③ 执行本地事务 │ │
│ ┌────────────┐ │ │
│ │ 本地事务 │ │ │
│ └────────────┘ │ │
│ │ │
│ ④ Commit / Rollback │ │
│─────────────────────►│ │
│ │ ⑤ 投递到真实 Topic │
│ │────────────────────►│
│ │ │
│ ⑥ 回查(超时未收到确认) │
│◄─────────────────────│ │
四个关键点:
- 半消息 :先发到 Broker,但存在
RMQ_SYS_TRANS_HALF_TOPIC,消费者看不到 - 本地事务:半消息发成功之后,才执行本地事务
- Commit / Rollback:按本地事务结果,决定把消息「放出来」还是「删掉」
- 回查 :Broker 长时间没收到确认,会主动问生产者(
checkLocalTransaction)
回查的默认参数:
| 参数 | 默认值 | 含义 |
|---|---|---|
transactionTimeOut |
6 秒 | 多久没收到确认就开始回查 |
transactionCheckInterval |
60 秒 | 回查间隔 |
transactionCheckMax |
15 次 | 最多回查几次,超过就丢弃 |
一句话 :事务消息保证的是最终一致 ,不是强一致------它只保证消息最终会被投递或丢弃,不保证消费端一定处理成功。
四、延时消息
是什么 :消息发送后不立即投递,等指定时间后才被消费者拿到。
典型场景:订单超时未支付自动取消、定时提醒。
实现原理:
- 消息先发到内部 Topic
SCHEDULE_TOPIC_XXXX - Broker 的定时任务扫描,到期的消息才被投递到真实 Topic
- 消费者这时才看得到
⚠️ 版本差异(常被问):
| 版本 | 支持情况 |
|---|---|
| 4.x 开源版 | 只支持 18 个固定级别:1s、5s、10s、30s、1m、2m、3m、4m、5m、6m、7m、8m、9m、10m、20m、30m、1h、2h |
| 5.0 起 | 支持任意时间(最大 40 天) |
坑:4.x 里想延时 7 分钟做不到,只能选最接近的固定级别(5m 或 10m)。
五、四种类型对比
| 类型 | 解决什么 | 代价 | 典型场景 |
|---|---|---|---|
| 普通消息 | 异步解耦 | --- | 大部分场景 |
| 顺序消息 | 严格按序处理 | 并发度下降 | 订单状态流转、binlog 同步 |
| 事务消息 | 本地事务与发消息的原子性 | 实现复杂、有回查开销 | 分布式事务最终一致 |
| 延时消息 | 定时触发 | 4.x 只支持固定级别 | 订单超时取消 |
选型口诀:
- 只要解耦异步 → 普通消息
- 同一实体的消息不能乱序 → 顺序消息
- 本地操作和发消息必须一致 → 事务消息
- 要「过一会儿再处理」 → 延时消息
六、总结
- 普通消息:看要不要知道发送结果,决定同步 / 异步 / 单向。
- 顺序消息:生产端按业务 Key 选 Queue + 消费端加锁串行;只保证单队列有序,代价是并发度下降。
- 事务消息:半消息 + 本地事务 + Commit/Rollback + 回查;保证最终一致,不保证消费成功。
- 延时消息:4.x 只有 18 个固定级别,5.0 起才支持任意时间。