「一文拿下 MQ」系列开篇。前两年(2017)把 JVM 系列写完之后,工程里另一个高频组件就是消息队列——它和锁、GC 一样,是后端面试和线上事故的高发地带。这个系列先讲 RabbitMQ(4 篇),再讲 Kafka(3 篇)。第一篇不急着进 Rabbit,先把「为什么用 MQ」和「选哪个 MQ」这两个最根本的问题讲透。
一、为什么用 MQ
引入 MQ 的本质动机只有三个词:解耦、异步、削峰。
1.1 解耦
系统之间不直接依赖,代码逻辑变更或新加入模块改动较小,单独系统故障不影响其他业务。
没有 MQ:
A → B
A → C A 直接调 B/C/D,任何一方变更都要改 A
A → D
引入 MQ:
A → MQ → B
→ C A 只管投递,B/C/D 谁订阅谁消费,互不感知
→ D
经典场景:下单后触发积分、推送、库存、风控——如果走同步调用,积分系统挂了你下单就失败。MQ 把这些「下游副作用」从主流程剥离,主流程只负责「下单成功」这一件事。
1.2 异步
同时调用多个服务时,把非核心链路的调用改成异步,提高主流程效率。
同步:A → B(200ms)→ C(300ms)→ D(500ms) 总耗时 1000ms
异步:A → MQ(5ms)→ B/C/D 并行处理 总耗时 ~5ms + 业务返回
注意:异步的前提是「这些操作不需要立即拿到结果」。如果 B/C/D 的返回值是 A 必须的,那就不能改成异步——这是新手最容易踩的坑。
1.3 削峰填谷
流量突增时,MQ 作为缓冲层保护下游数据库/服务不被打挂。
秒杀场景:
前端 10w QPS → MQ(堆积)→ 后端按自己的处理速度(如 1k QPS)消费
削峰的本质是用排队换系统的稳定。代价是消息延迟——所以叫「填谷」:高峰时堆在 MQ 里,等流量回落再慢慢消化。这也是为什么秒杀场景的「下单成功」往往需要走异步通知。
二、MQ 技术选型考虑因素
选 MQ 不是看哪个「最厉害」,而是看哪个最匹配你的业务。需要考虑的维度:
| 维度 | 关键问题 |
|---|---|
| 性能 | 单机吞吐量多少?延迟多少?消息堆积能力? |
| 可靠性 | 消息会丢吗?是否支持 ACK、重试、死信? |
| 功能 | 是否支持延迟队列、事务消息、优先级、TTL? |
| 集群 | 集群架构?高可用方案?可扩展性? |
| 运维 | 监控界面?社区活跃度?文档完善度? |
| 成本 | 人员学习成本、运维成本、机器成本 |
一句话:没有最好的 MQ,只有最合适的 MQ。
三、四种主流 MQ 横评
3.1 ActiveMQ
- 成熟,老牌 MQ
- 单机吞吐量万级
- 近年更新维护相对不活跃
- 适合:历史遗留系统、轻量场景
3.2 RabbitMQ
- 社区活跃,功能完备
- 单机吞吐量万级
- 管理界面强大(自带 web UI)
- Erlang 语言开发,不便于定制研究
- 适合:业务消息、可靠投递、复杂路由
3.3 RocketMQ
- 单机吞吐量十万级
- MQ 功能完备(死信队列、延迟队列、事务消息)
- 分布式扩展方便
- 阿里出品,Java 实现
- 适合:业务复杂、吞吐量高、需要事务消息
3.4 Kafka
- 单机吞吐量十万级(超高)
- 易于扩展,分布式设计
- MQ 功能较简单(不支持延迟队列;事务消息 0.11+ 已支持)
- 适合:大数据领域、日志采集、流式处理
3.5 速查对比表
| 维度 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 单机吞吐量 | 万级 | 万级 | 十万级 | 十万级 |
| 时效性 | μs 级 | μs 级 | ms 级 | ms 级 |
| 可用性 | 高(主从) | 高(主从) | 很高(分布式) | 很高(分布式) |
| 消息可靠性 | 较低 | 高 | 高 | 高 |
| 功能丰富度 | 中 | 高(路由灵活) | 高(事务/延迟/死信) | 低(核心发布订阅) |
| 开发语言 | Java | Erlang | Java | Scala/Java |
| 典型场景 | 老系统 | 业务消息、复杂路由 | 金融/电商事务 | 大数据、日志、流处理 |
经验法则:
- 业务消息、需要复杂路由、中小吞吐量 → RabbitMQ
- 大吞吐、需要事务/延迟/死信 → RocketMQ
- 日志、大数据、流处理 → Kafka
- 不要再为新项目选 ActiveMQ
四、RabbitMQ 入门:AMQP 协议
本系列前 4 篇的主角是 RabbitMQ。它实现的核心协议叫 AMQP(Advanced Message Queuing Protocol,高级消息队列协议)。
4.1 AMQP 的三大核心组件
AMQP 模型由三个主要模块构成:
| 组件 | 作用 |
|---|---|
| Exchange(交换机) | 接收生产者发送的消息,根据路由规则分发到队列 |
| Queue(队列) | 存储消息,消费者从队列拉取消息 |
| Binding(绑定) | 连接 Exchange 和 Queue 的规则(含 routing key) |
Producer → Exchange ──binding(routing key)──→ Queue → Consumer
↑
│
消息路由的核心
生产者不直接发消息给队列,而是发给 Exchange;Exchange 根据绑定规则决定投递到哪个队列。这是 RabbitMQ 与其他 MQ 最大的区别——它的路由模型非常强大。
4.2 四种 Exchange 类型
| 类型 | 路由规则 | 典型场景 |
|---|---|---|
| Direct | routing key 完全匹配 | 点对点精准投递 |
| Fanout | 广播到所有绑定队列(忽略 routing key) | 广播通知、配置推送 |
| Topic | routing key 模式匹配(* 匹配一段、# 匹配多段) | 最常用,按业务前缀订阅 |
| Headers | 根据消息 headers 匹配(不用 routing key) | 少见,灵活但性能差 |
Topic 是实战中最常用的。比如 routing key 用
order.pay.success、order.refund.fail,消费者订阅order.#就能收到所有订单事件。
五、本系列后续规划
| 篇 | 主题 | 重点 |
|---|---|---|
| 上(本篇) | 为什么用 MQ + 选型对比 | 解耦/异步/削峰、四大 MQ 横评、AMQP 协议入门 |
| 中 | 安装与命令 | Erlang/RabbitMQ 安装、rabbitmqctl 速查、web 监控 |
| 下 | Spring Boot 集成 | 配置、生产者 Confirm、消费者 @RabbitListener |
| 末 | 集群与高可用 | 普通集群、镜像队列、Warren/Shovel 模式 |
下一篇「消息队列(中):RabbitMQ 安装与命令速查」进入实战——怎么装、怎么管、怎么看。
现代视角补一句(2026):选型表里的数字到 2026 年依然大致成立——RabbitMQ 万级、Kafka/RocketMQ 十万级。变的只是细节:RabbitMQ 引入了 Quorum Queue(基于 Raft 的仲裁队列,替代镜像队列)、Kafka 的 KRaft 模式去掉了 ZooKeeper 依赖。但选型逻辑八年来没变过。