在微服务项目中,消息队列几乎是绕不开的一部分。
比如用户下单后,系统可能需要同时完成:
- 扣减库存
- 增加积分
- 发送短信
- 通知物流
- 记录操作日志
如果这些操作全部同步执行:
下单
↓
扣库存
↓
加积分
↓
发短信
↓
通知物流
↓
返回结果
整个接口会越来越慢,而且其中一个服务出现问题,还可能影响整个调用链。
引入消息队列之后,可以把部分操作异步化:
→ 库存服务
订单服务 → MQ → 积分服务
→ 短信服务
→ 物流服务
因此消息队列最常见的作用可以概括成三个词:
异步、削峰、解耦。
但实际学习 MQ 时,很快又会遇到另一个问题:
RabbitMQ、RocketMQ、Kafka 都是消息队列,它们到底有什么区别?
这一篇就重点解决这个问题。
1. 先看整体区别
如果先不考虑各种底层细节,可以这样理解:
| RabbitMQ | 路由灵活、传统消息能力完善 | 普通业务消息 |
| RocketMQ | 业务型消息能力丰富 | 电商、订单、交易 |
| Kafka | 高吞吐、消息持久保存、可重复消费 | 日志、大数据、事件流 |
先记住一个非常粗略的印象:
RabbitMQ → 灵活
RocketMQ → 业务
Kafka → 吞吐
当然这并不是说 RabbitMQ 吞吐一定低,也不是说 Kafka 不能做业务消息。
区别主要在于它们最擅长解决的问题不同。
2. RabbitMQ:传统业务消息队列
RabbitMQ 是非常典型的 Broker 型消息队列。
它最大的特点之一,就是消息路由机制比较灵活。
RabbitMQ 中通常不是生产者直接把消息发送给 Queue,而是:
Producer
↓
Exchange
↓
Queue
↓
Consumer
其中 Exchange 会根据规则决定消息进入哪个队列。
常见 Exchange 包括:
Direct
Topic
Fanout
Headers
例如一个订单事件:
order.created
可以根据 Routing Key 分发给不同队列:
→ 库存队列
Producer → Exchange → 积分队列
→ 通知队列
因此 RabbitMQ 很适合传统业务系统中的:
- 订单通知
- 邮件发送
- 短信发送
- 后台任务
- 服务之间异步通信
另外 RabbitMQ 对消息确认机制支持得也比较完善。
例如消费者处理成功后发送 ACK:
RabbitMQ
↓
Consumer
↓
业务执行成功
↓
ACK
如果消费者没有正常确认消息,Broker 可以重新投递。
RabbitMQ 当前的高可用场景中还提供基于 Raft 的 Quorum Queue,适合需要复制和高可用的队列场景。
所以 RabbitMQ 给人的整体感觉是:
更像一个专业的“消息传递系统”。
3. RocketMQ:更偏业务场景
RocketMQ 同样属于消息队列,但它和 RabbitMQ 的设计侧重点并不完全一样。
RocketMQ 中比较常见的结构是:
Producer
↓
Topic
↓
MessageQueue
↓
Consumer
RocketMQ 最大的优势之一,是对很多业务场景提供了比较直接的支持。
例如:
顺序消息
假设订单状态依次发生:
创建订单
↓
支付订单
↓
发货
↓
完成
对于同一个订单,这几个事件不能乱。
RocketMQ 可以通过消息分组等机制,让同一组消息按照顺序进行处理。
延迟消息
例如:
用户下单
↓
30分钟没有支付
↓
自动关闭订单
RocketMQ 提供延时/定时消息能力,可以让消息到指定时间之后再对消费者可见。
事务消息
还有一个非常典型的场景:
创建订单成功
+
发送订单消息成功
如果数据库操作成功,但 MQ 消息没发送出去,就可能产生数据不一致。
RocketMQ 提供事务消息,用来处理本地业务操作和消息发送之间的一致性问题。
因此 RocketMQ 经常出现在:
电商
订单
支付
库存
交易
营销
这类业务系统中。
所以可以把 RocketMQ 理解成:
不仅仅负责传消息,还提供了很多围绕业务消息设计的能力。
4. Kafka:更像分布式事件日志
Kafka 虽然经常和 RabbitMQ、RocketMQ 放在一起比较,但它的设计思想其实有一些不同。
Kafka 官方更倾向于把自己定义为:
Event Streaming Platform,事件流平台。
Kafka 中:
Producer
↓
Topic
↓
Partition
↓
Consumer
Topic 会被划分成多个 Partition:
Topic: order
Partition 0
Partition 1
Partition 2
Partition 3
不同 Partition 可以并行读写,因此 Kafka 非常容易进行水平扩展。
而 Kafka 还有一个非常重要的特点:
消息被消费之后,并不会马上删除。
消费者只是记录:
我消费到 offset = 100 了
消息本身仍然可以按照配置继续保存。
所以消费者可以重新调整 offset:
offset = 100
↓
offset = 50
然后重新读取之前的数据。
因此 Kafka 特别适合:
- 日志采集
- 用户行为数据
- 埋点数据
- CDC 数据同步
- 实时计算
- 大数据处理
- 事件驱动架构
例如:
订单数据库
↓
Kafka
↓
┌────────────┐
↓ ↓
Flink 数据仓库
↓ ↓
实时统计 离线分析
所以 Kafka 与传统 MQ 最大的思维区别之一是:
RabbitMQ / RocketMQ
更关注:
消息有没有正确送到消费者
Kafka
更关注:
事件有没有可靠地记录下来,并能够持续被处理
5. 三者真正应该怎么选?
最后把几个最容易混淆的地方放在一起比较。
| 主要定位 | 消息中间件 | 分布式消息中间件 | 事件流平台 |
| 路由能力 | 很强 | 较强 | 相对简单 |
| 高吞吐场景 | 可以 | 很强 | 非常擅长 |
| 顺序消息 | 支持一定顺序能力 | 原生业务能力较完善 | Partition 内有序 |
| 延迟消息 | 通常通过 TTL、DLX 等方案实现 | 原生支持 | 通常需要额外设计 |
| 事务相关 | Publisher Confirm 等 | 事务消息 | Producer Transaction |
| 消息回溯 | 不是核心使用方式 | 支持一定程度回溯 | 非常适合 |
| 典型场景 | 普通微服务业务 | 电商、订单、交易 | 日志、大数据、实时流 |
实际项目里,可以简单按照需求判断。
普通微服务异步任务
例如:
发送短信
发送邮件
异步通知
后台任务
可以优先考虑:
RabbitMQ
电商、订单、交易系统
如果经常需要:
顺序消息
延迟消息
事务消息
那么:
RocketMQ
通常会比较合适。
日志、埋点、实时数据
如果系统特点是:
数据量非常大
需要长期保存
需要重复消费
需要 Flink / Spark 等实时计算
那么:
Kafka
往往更加适合。
总结
RabbitMQ、RocketMQ 和 Kafka 看起来都在做:
Producer → MQ → Consumer
但背后的设计目标却各有侧重,并不完全相同。
所以选择 MQ 时,不应该只看中:
哪个消息队列性能最好?
而是
我的系统究竟需要解决什么问题?
如果只是普通业务异步通知,RabbitMQ 已经很好用;如果有大量订单、延迟和事务类需求,可以重点考虑 RocketMQ;如果面对的是海量事件数据以及实时计算,那么 Kafka 往往更加合适。
理解了这一点,再去学习每个 MQ 的 Producer、Consumer、Topic、Queue、ACK、Offset 等具体机制,就会清晰很多。


