来源:北哥 | 发布日期:2026-05-22
选型原则:需求先行
选型最大的坑是「先看产品特性,再往自己业务上套」。正确顺序:先把业务场景和核心诉求写下来,再对照产品。
典型的业务需求维度:
| 维度 | 要求示例 | 权重 |
|---|---|---|
| 消息可靠性 | 不能丢,需重试机制 | 高 |
| 延迟消息 | 下单30分钟未支付自动取消 | 高 |
| 事务消息 | 解决分布式事务问题 | 高 |
| 吞吐量 | 百万级/天,非极端场景 | 中 |
| 运维成本 | 小团队,无专职 MQ 运维 | 高 |
| 学习成本 | 团队大部分没深入用过 MQ | 中 |
三款 MQ 对比
RabbitMQ
成熟最早(2007),用户群体最广。
- 优势:延迟极低(微秒级)、路由规则灵活(Exchange + Binding)、管理界面友好、社区成熟
- 劣势:吞吐上限低(万级/秒)、Erlang 实现排查困难、延迟消息需死信队列 + TTL 模拟
- 适合:消息量不大、路由规则复杂、有 Erlang 运维能力的场景
Kafka
大数据领域事实标准。
- 优势:吞吐量极高(百万级/秒)、持久化好、与 Flink/Spark 生态无缝集成
- 劣势:不支持延迟消息(硬伤)、功能偏底层(无死信队列/消费重试)、运维复杂(需专人)
- 适合:日志收集、大数据流处理、有专职运维的场景
RocketMQ
阿里 2012 年开源,专为电商业务消息设计。
- 优势:原生 18 级延迟消息、原生事务消息(半消息 + 回查)、默认 16 次阶梯式重试、死信队列内置、Java 实现便于排查
- 劣势:非 Java 生态支持弱(Python/Go 客户端不成熟)、社区活跃度不如前两者
- 适合:业务消息场景、Java 技术栈、需要延迟/事务消息的团队
核心特性对比
| 特性 | RabbitMQ | Kafka | RocketMQ |
|---|---|---|---|
| 吞吐量 | 万级/秒 | 百万级/秒 | 十万级/秒 |
| 消息延迟 | 微秒级 | 毫秒级 | 毫秒级 |
| 延迟消息 | 需插件模拟 | ❌ 不支持 | ✅ 原生 18 级 |
| 事务消息 | ❌ | ❌(方案复杂) | ✅ 原生支持 |
| 消费重试 | 需自行实现 | 需自行实现 | ✅ 默认 16 次 |
| 死信队列 | 需配置 | ❌ | ✅ 自动进入 |
| 运维难度 | 低 | 高 | 中 |
| 开源语言 | Erlang | Scala/Java | Java |
| 适用场景 | 复杂路由/低延迟 | 大数据/日志 | 业务消息/电商 |
决策过程
第一步:排除 Kafka
有延迟消息需求(下单30分钟未支付自动取消),Kafka 原生不支持,自行实现维护成本高,直接排除。
第二步:RabbitMQ vs RocketMQ
三个核心需求对比:
- 延迟消息:RocketMQ 原生 18 个延迟级别(1s/5s/10s/30s/1m/2m...2h),一行配置搞定。RabbitMQ 需 TTL Queue + 死信队列,绕三层且不灵活。
- 事务消息:RocketMQ 直接支持。RabbitMQ 需本地消息表 + 重试,代码量大。
- 消费重试:RocketMQ 内置阶梯式重试(1s→5s→...→16次后进死信队列),零代码。RabbitMQ 需自行处理。
第三步:看团队匹配度
团队全是 Java 栈,RocketMQ 是 Java 实现,遇问题可直接读源码。国内大厂广泛使用,中文资料丰富。
上线后踩坑
坑一:NameServer 地址没配全
只配了一个 NameServer,该节点重启期间生产者偶尔连不上。解决:配全所有节点地址。
rocketmq.name-server=192.168.1.1:9876;192.168.1.2:9876
坑二:消费者线程数没调
默认消费者线程数 20,Topic 消息量上来后开始堆积。增加到 64 后恢复正常。
consumer.setConsumeThreadMin(20);
consumer.setConsumeThreadMax(64);
坑三:延迟消息级别固定
RocketMQ 只有预设 18 个延迟级别,不支持任意秒级延迟。如果业务需要精确到秒的延迟(如 37 秒),需改用 Redis ZSet 或商业版。30 分钟未支付场景用第 14 级(20 分钟)加兜底查询可解决。
选型 Checklist
- 有延迟消息需求? → 直接排除 Kafka
- 有事务消息需求? → RabbitMQ 原生不支持
- 团队规模多大? → Kafka 运维成本高,小团队慎重
- 消息量级? → 百万级/天 vs 百万级/秒,差距很大
- 主要技术栈? → 语言不匹配会导致客户端支持差