RocketMQ 都有哪些消息类型?使用场景是什么?面试回答RocketMQ 5.x 按消息的传输语义正式分为四种类型:

普通消息 Normal:没有顺序、定时或事务等特殊语义,发送成功后即可被消费,适合微服务解耦、异步通知、日志和数据集成。顺序消息 FIFO:同一 Message Group 内的消息按照发送、存储和投递顺序处理,适合同一订单的创建、支付、发货等状态流转,以及 Binlog 增量同步。定时与延时消息 Delay:消息到指定时间后才对消费者可见,适合订单超时关闭、延迟检查、定时通知和任务调度。事务消息 Transaction:通过半事务消息、本地事务确认和事务回查,保证本地事务与消息发送的最终一致性,适合下单后发放积分、扣款后发送通知等场景。RocketMQ 5.x 可以为 Topic 声明消息类型,一个 Topic 只应承载一种消息类型。批量消息属于发送方式,重试消息和死信消息属于消费失败后的系统处理状态,Request-Reply 属于通信模式,它们都不属于上述四种正式 MessageType。

一句话总结:

无特殊要求用普通消息;同一业务实体需要按序处理用 FIFO;需要未来触发用 Delay;本地事务必须和消息发送保持最终一致用 Transaction。

一张图看懂

详细讲解一、先明确 RocketMQ 的正式分类RocketMQ 5.x 定义了四种 MessageType:

消息类型核心语义典型场景NORMAL发送后立即进入可消费状态异步解耦、事件通知、日志传输FIFO同一 Message Group 内按顺序处理订单状态流转、Binlog 同步DELAY到指定时间后才允许消费超时关闭、延迟检查、定时任务TRANSACTION本地事务与消息发送最终一致交易完成后驱动下游业务这四种类型不是按照消息内容划分,而是按照消息需要具备的传输和投递语义划分。

例如,同样是“订单创建”事件:

创建后立即异步通知风控,可以使用普通消息;必须与后续支付、发货事件保持同一订单内的顺序,可以使用顺序消息;创建三十分钟后检查是否支付,可以使用延时消息;只有订单数据库事务成功后才能向下游投递,可以使用事务消息。因此,消息类型的选择取决于业务语义,而不是消息中装了什么数据。

二、普通消息 Normal1. 什么是普通消息普通消息没有顺序、定时和事务等特殊语义。Broker 接收并保存消息后,消息进入 Ready 状态,Consumer 可以正常获取并处理。

⧉ 复制Producer

│ 发送

▼

Broker 持久化

│ 立即可见

▼

Consumer 消费

“普通”不代表不可靠。普通消息同样可以使用发送确认、Broker 持久化、消费重试、死信队列和业务幂等机制。

它只表示:

消息之间没有需要 RocketMQ 额外维护的顺序、时间或事务关系。

2. 适用场景普通消息适合绝大多数异步业务:

微服务之间异步解耦;用户注册后异步发送欢迎短信;订单创建后异步更新搜索索引;操作日志、埋点和审计事件传输;缓存失效通知;数据采集和数据集成;不要求严格顺序的业务事件广播。例如,订单创建后需要通知多个独立系统:

⧉ 复制订单服务

│

└── OrderCreated 普通消息

├── 风控服务

├── 推荐服务

└── 数据分析服务

这些下游之间不存在必须先后执行的关系,使用普通消息能够获得更好的并发能力。

3. 不适合的场景以下要求不能只依赖普通消息:

同一订单的支付必须在创建之后处理;消息必须在未来某个时间触发;本地数据库事务失败时消息绝对不能对下游可见。这时应分别考虑 FIFO、Delay 或 Transaction。

三、顺序消息 FIFO1. 顺序消息保证什么RocketMQ 5.x 使用 Message Group 标识需要保持顺序的一组消息。同一个 Message Group 中的消息按照先进先出顺序处理。

例如以订单号作为 Message Group:

⧉ 复制Message Group = order-1001

创建订单 → 支付成功 → 仓库出库 → 物流发货

另一个订单可以使用不同的 Message Group:

⧉ 复制order-1001:创建 → 支付 → 发货

order-1002:创建 → 取消

两个订单之间不要求顺序,可以并发处理;同一订单内部保持顺序。这通常称为局部顺序或分组顺序。

2. 为什么不追求整个 Topic 的全局顺序如果一个 Topic 的全部消息都要求全局顺序,就只能把所有消息串行发送、存储和消费,并发能力会受到严重限制。

按订单号、用户 ID、账户 ID 等业务键划分 Message Group,可以做到:

⧉ 复制组内有序

+

组间并行

这更符合大多数业务的真实要求。

3. 保证顺序需要满足哪些条件完整的顺序需要覆盖三个阶段。

发送顺序同一 Message Group 的消息需要由生产端按业务顺序串行发送。如果多个线程或多个生产者同时发送,即使 Message Group 相同,RocketMQ 也无法推断业务上谁应该在前。

存储顺序RocketMQ 将同一 Message Group 的消息存入同一个队列,并保持接收顺序。

消费顺序Consumer 必须遵循“接收、处理、确认”的顺序。不能收到消息后随意提交给异步线程并立即确认,否则业务实际完成顺序仍可能被打乱。

⧉ 复制发送有序

↓

存储有序

↓

投递有序

↓

业务处理有序

4. 适用场景同一订单的创建、支付、取消和发货;同一账户的充值、扣款和退款;同一用户的状态变更;数据库 Binlog 增量同步;工作流节点推进;交易撮合等要求按到达顺序处理的场景。5. 使用代价与风险顺序消息会牺牲部分并发能力,并且前面的消息处理失败时,后续消息可能等待。

需要重点关注:

Message Group 是否过热;单条消息是否持续重试并阻塞后续消息;消费逻辑是否包含慢 SQL、慢 RPC;是否错误地在消费端进行异步并发处理;是否真的需要顺序,还是使用状态机和幂等就能解决。不要把所有消息都设置为同一个 Message Group,否则会把系统退化成串行消费。

四、定时与延时消息 Delay1. 定时消息和延时消息有什么区别业务表达方式不同,但在 RocketMQ 5.x 中本质相同:都是设置一个未来的投递时间戳。

⧉ 复制延时消息:10 分钟后投递

定时消息:2026-07-26 18:00:00 投递

延时消息也需要先计算出最终投递时间:

⧉ 复制long deliveryTimestamp =

System.currentTimeMillis() + Duration.ofMinutes(10).toMillis();

2. 消息生命周期⧉ 复制Producer 发送

↓

Timing:Broker 按时间暂存

↓ 到达投递时间

Ready:转入普通存储并对 Consumer 可见

↓

Consumer 消费并确认

消息到达 Broker 并不代表 Consumer 立即可见。只有达到投递时间,消息才进入可以消费的状态。

3. 适用场景订单创建三十分钟后检查是否支付;支付处理中,五分钟后查询渠道结果;优惠券到期提醒;用户预约通知;延迟重试;定时清理任务;分布式定时调度。例如订单超时关闭:

⧉ 复制创建订单

│

├── 写入订单数据

└── 发送 30 分钟后投递的 Delay 消息

↓

Consumer 查询订单状态

├── 未支付:关闭订单

└── 已支付:忽略消息

Consumer 收到延时消息后仍然必须重新检查业务状态。消息表达的是“现在应该检查”,不是“订单一定未支付”。

4. 延时消息不是精确定时器设置的时间表示消息不应早于该时间被消费,但以下因素可能使实际处理晚于目标时间:

Broker 当前负载较高;大量消息设置了相同投递时间;消费端发生积压;Consumer 执行较慢或暂时不可用;存储系统故障或重启。因此,对秒级严格准点有强要求的业务不能只依赖消息到达时间,还要监控投递延迟并准备补偿扫描。

5. RocketMQ 4.x 与 5.x 的区别RocketMQ 4.x 常见实现使用固定的延迟级别,例如:

⧉ 复制1 秒、5 秒、10 秒、30 秒、1 分钟……

生产者通过 delayTimeLevel 选择预设级别。

RocketMQ 5.x 的正式 Delay 消息使用毫秒级 Unix 时间戳表示投递时间,不再局限于旧版固定延迟级别。面试时需要先说明讨论的是哪个版本,避免把 4.x 的十八个延迟级别直接当作 5.x 的唯一实现。

五、事务消息 Transaction1. 事务消息解决什么问题事务消息解决的是:

本地事务与消息发送之间的最终一致性。

例如订单服务需要同时完成:

在本地数据库创建订单;向 RocketMQ 发送订单创建消息。如果先提交数据库再发送消息,数据库成功后消息可能发送失败;如果先发送消息再写数据库,消息可能已被消费,但数据库事务最终失败。

⧉ 复制数据库事务成功,消息失败 → 下游永远不知道订单已创建

消息发送成功,数据库失败 → 下游处理了一笔不存在的订单

2. 核心流程⧉ 复制Producer 发送 Half Message

↓

Broker 保存消息,但暂不向 Consumer 投递

↓

Producer 执行本地事务

┌───┴────────┐

│ │

Commit Rollback

│ │

消息可见并投递 消息回滚

如果 Broker 长时间没有收到明确结果,会回查 Producer:

⧉ 复制Broker 发起事务回查

↓

Producer 查询本地事务记录

┌────┼─────┐

Commit Unknown Rollback

Producer 的事务回查不能只依赖内存变量,需要根据订单表、事务日志或本地 Outbox 等持久化数据判断。

3. 适用场景订单创建成功后通知库存、积分系统;扣款成功后发送账务事件;账户入账成功后通知下游;数据库状态变化后更新搜索索引;本地事务成功后驱动跨服务异步流程。4. 事务消息不保证什么事务消息保证的是本地事务与消息是否投递之间的最终一致性,不等于整个分布式业务已经成功。

例如:

⧉ 复制订单本地事务成功

↓

事务消息 Commit

↓

积分服务消费失败

RocketMQ 可以重试投递,但积分服务仍需实现:

消费幂等;失败重试;死信处理;对账与补偿;业务状态机。事务消息也不是跨多个数据库的强一致分布式事务。它更适合能够接受异步执行和最终一致性的业务。

六、四种消息类型如何选择可以按照下面的顺序判断:

⧉ 复制本地事务是否必须与消息发送保持最终一致?

├── 是 → Transaction

└── 否

↓

消息是否需要到未来某个时间才可消费?

├── 是 → Delay

└── 否

↓

同一业务实体的事件是否必须按顺序处理?

├── 是 → FIFO

└── 否 → Normal

对应关系:

业务要求推荐类型关键设计点只需要可靠异步传输Normal重试、幂等、监控同一订单内有先后关系FIFOMessage Group、串行处理未来某个时间触发Delay投递时间、状态复查、延迟监控本地事务成功后才能投递TransactionHalf Message、事务回查、持久化事务状态不要因为高级消息类型“功能更多”就默认使用。每种特殊语义都会增加约束、运维成本或吞吐损耗;没有特殊要求时,普通消息通常是更简单的选择。

七、这些算不算消息类型1. 批量消息批量消息不是独立 MessageType,而是一种发送或消费方式。

⧉ 复制单条发送:一次请求发送一条消息

批量发送:一次请求携带多条消息

批量能够减少网络往返和请求开销,适合日志采集、数据同步等吞吐优先的场景,但需要注意:

控制整个批次的大小;批次失败后的重试粒度;顺序消息不应随意并行批处理;批量消费部分成功时的幂等和重试问题。2. 重试消息重试消息是普通消息、FIFO 消息等消费失败后,RocketMQ 根据消费重试策略重新投递形成的系统处理过程,不是业务创建 Topic 时选择的正式 MessageType。

对于 PushConsumer,一次消费及失败重试可以简化为:

⧉ 复制Ready

↓ Consumer 获取消息

Inflight

├─ 消费成功并返回结果 → Commit

└─ 消费失败或等待结果超时 → WaitingRetry

├─ 到达重试时间 → Ready

└─ 超过最大重试次数 → DLQ

Inflight 表示消息已经被 Consumer 获取,Consumer 正在执行业务逻辑,但消费结果还没有返回给 Broker。它可以理解为“正在处理中、等待确认”,不是一种新的消息类型。

WaitingRetry 是 PushConsumer 重试状态机中的状态。消息消费失败或 Broker 等待消费结果超时后,如果尚未达到最大重试次数,消息会先进入 WaitingRetry;重试间隔结束后重新回到 Ready,等待下一次投递。

Consumer 必须按消息可能重复投递来设计幂等。

3. 死信消息消息超过最大消费重试次数后,可能进入死信队列。死信消息代表消息进入异常隔离状态,也不是四种正式业务 MessageType 之一。

死信队列需要配套:

告警;失败原因记录;人工检查;修复后的重投;对账和业务补偿。4. Request-Reply 消息Request-Reply 是一种通信模式:

⧉ 复制请求方发送消息

↓

处理方消费并返回响应

↓

请求方等待响应

它描述生产者和消费者如何交互,不属于 NORMAL、FIFO、DELAY、TRANSACTION 之外的第五种正式 MessageType。

5. 同步、异步和单向消息同步发送、异步发送和单向发送描述的是 Producer 调用发送接口的方式,也不是消息类型。

⧉ 复制同步发送:等待 Broker 返回结果

异步发送:通过回调接收结果

单向发送:发送后不等待结果

不要把“发送方式”和“消息传输语义”混为一谈。

八、RocketMQ 5.x 为什么要求 Topic 类型一致RocketMQ 5.x 支持在 Topic 上声明消息类型:

⧉ 复制./bin/mqadmin updateTopic \

-n 127.0.0.1:9876 \

-t order-events \

-c DefaultCluster \

-a "+message.type=FIFO"

其中:

-n 指定 NameServer 地址;-t 指定 Topic 名称;-c 指定目标集群;message.type 可设置为 NORMAL、FIFO、DELAY 或 TRANSACTION。上面创建的是 FIFO Topic。创建其他类型时,只需要替换最后一个参数的类型值。

启用类型校验后,一个 Topic 只允许发送与其类型一致的消息。例如:

FIFO 消息不能发送到 NORMAL Topic;TRANSACTION 消息不能发送到 DELAY Topic;同一个 Topic 不应同时承载普通消息和顺序消息。这样做的价值是:

让 Topic 的行为语义清晰;避免客户端误用高级消息能力;便于 Broker 按消息类型管理;降低运维和故障排查复杂度。为了兼容旧客户端,5.x 的强制类型校验能力需要结合服务端配置判断。面试中可以说“5.x 支持并推荐一个 Topic 对应一种消息类型”,不要绝对化为所有兼容部署都默认强制拒绝。

九、常见追问1. 普通消息一定无序吗普通消息在某个物理队列中自然存在存储先后,但业务没有建立端到端 FIFO 约束。多队列发送、并发消费、失败重试都可能使业务完成顺序变化,因此不能依赖普通消息保证业务顺序。

2. 顺序消息能否保证整个 Topic 全局有序实际通常保证同一 Message Group 内有序。理论上把所有消息放入一个组可以接近全局串行,但会形成热点并严重限制吞吐,不建议这样设计。

3. 延时消息到点后一定立即执行吗不一定。到点表示消息可以进入可消费状态,Broker 调度延迟、消息积压和 Consumer 处理能力都会影响最终业务执行时间。

4. 事务消息消费成功是否与本地事务强一致不是。事务消息只保证本地事务结果与消息是否投递之间的最终一致性。Consumer 的业务处理仍然是独立的异步过程,需要重试、幂等和补偿。

5. FIFO 和 Transaction 能否同时使用从 RocketMQ 5.x 的 Topic 类型模型看,一个 Topic 只对应一种正式消息类型,不能把同一条消息同时声明为 FIFO 和 Transaction。业务同时需要“事务一致性”和“顺序处理”时,需要重新审视领域流程,常见做法是用事务消息可靠发布业务事件,再由下游状态机、版本号、业务序号或独立 FIFO 流程处理顺序要求。

十、容易答错的地方错误一:RocketMQ 有五种消息,包含批量消息批量是发送方式,不是 RocketMQ 5.x 的正式 MessageType。正式类型是 Normal、FIFO、Delay、Transaction。

错误二:顺序消息保证整个 Topic 全局有序通常保证同一 Message Group 内的局部顺序,不同组之间允许并发。

错误三:延时消息到了时间就保证业务已经执行到达投递时间只表示消息对 Consumer 可见,实际业务完成还受积压、消费能力和重试影响。

错误四:事务消息保证上下游所有业务一起提交事务消息保证本地事务与消息投递最终一致,下游消费结果仍然需要独立保障。

错误五:普通消息可靠性低普通消息只是没有高级传输语义,不代表不持久化、不重试或不可靠。

参考资料Apache RocketMQ 5.0:Topic 与 MessageTypeApache RocketMQ 5.0:普通消息Apache RocketMQ 5.0:顺序消息Apache RocketMQ 5.0:定时与延时消息Apache RocketMQ 5.0:事务消息Apache RocketMQ 5.0:消费重试Apache RocketMQ 4.x:延时消息级别