很多人聊MQ选型,都在背参数对比表,但真正上了生产才发现,选型根本不是看吞吐量,是看你的业务能不能扛住那个最烂的场景。
不聊概念,就拿真实业务场景,把选型逻辑讲透。
先把底层差异说清楚
很多人选MQ就看"谁快谁慢",这是错的。你得先理解它们的设计目标完全不一样:
Kafka:本质是个分布式日志系统。它的核心能力是高吞吐顺序写入 + 海量数据回放。broker是无状态的,数据存在本地磁盘,靠分区做水平扩展。消费者自己维护offset,broker不管你消费到哪了。
RocketMQ:阿里搞的,核心能力是可靠消息 + 延迟消息 + 事务消息。broker是有状态的,记录每个消费者的消费进度。天然支持消息回溯、死信队列、重试机制,这些是业务级功能,不是你自己能搞出来的。
RabbitMQ:Erlang写的,核心能力是灵活路由 + 协议丰富。它的Exchange-Queue-Binding模型让你能玩出花来,但吞吐量是三个里最拉的。适合路由逻辑复杂但QPS不高的场景。
一句话总结:
- 要吞吐 → Kafka
- 要可靠 + 业务功能 → RocketMQ
- 要路由灵活 → RabbitMQ
但这只是起点,真正的选型得看场景。
场景一:订单系统的异步通知
背景:用户下单后,需要异步发短信、推送、积分。日均订单50万,峰值8000QPS。要求:消息不能丢,至少发一次。
1.1 Kafka方案
Kafka吞吐量确实猛,8000QPS对它来说洒洒水。但问题来了------
Kafka的消费者offset是自己维护的,broker不管你消费成功没有。 你消费完了处理业务逻辑,业务逻辑成功了,你再去commit offset。但如果你commit之前进程挂了呢?offset没提交,重启后从上一个offset重新消费,消息就重复了。
你说加幂等?可以。但更恶心的问题是:Kafka不支持消息回溯。 业务说"我要重新发昨天的短信",Kafka做不到。你得自己写消费逻辑,把消息重新灌进去。
而且Kafka没有死信队列的概念。消费失败了怎么办?你得自己建个重试Topic,自己写重试逻辑,自己控制重试次数。这些东西RocketMQ原生就有。
1.2 RabbitMQ方案
RabbitMQ的可靠性靠的是ack机制 + 持久化。消费者ack了broker才删消息,看起来很可靠对吧?
但我们压测发现一个问题:RabbitMQ在队列积压超过10万条时,消费性能暴跌。 原因是它的队列是存在内存里的(虽然可以持久化到磁盘,但消费时还是要加载到内存),内存扛不住就开始swap,swap一上来延迟直接从毫秒级飙到秒级。
我们峰值的时候积压过20万条,RabbitMQ直接卡死了,消费者全部超时。
1.3 RocketMQ方案
最终选了RocketMQ,原因就三个:
- 死信队列原生支持:消费失败自动进死信队列,不用自己造轮子
- 消费进度broker端维护:你挂了重启,从断点继续消费,不丢不重
- 消息回溯:业务说"重新发一下上周的通知",RocketMQ控制台点一下就行,Kafka你得自己写
最终效果:日均50万消息,零丢失,消费延迟P99控制在200ms以内。
这个场景的结论:需要消息可靠 + 业务功能的,直接RocketMQ,别犹豫。
场景二:日志采集系统
背景:200个微服务的日志统一采集,日增量500GB,要求能存7天,支持按时间范围查询。
这个场景我们用的Kafka,而且用得很爽。
为什么不用RocketMQ?
因为RocketMQ扛不住这个写入量。
RocketMQ的broker是有状态的,每个broker要维护消费队列、偏移量、索引,单机写入上限大概在1万TPS左右。500GB/天 ≈ 6000条/秒(单条1KB),看起来不多对吧?但这是平均值,峰值的时候会飙到3万TPS,RocketMQ的broker直接扛不住,磁盘IO打满。
Kafka就不一样了。它的broker是无状态的,数据就是append到本地日志文件,磁盘顺序写,单机轻松扛10万TPS。而且Kafka的数据保留策略是按时间或按大小,天然适合日志场景。
更关键的是:我们需要回溯。 排查线上问题的时候,要能拉取某个时间段的日志。Kafka的offset机制天然支持"从某个时间点开始消费",而RocketMQ虽然也能回溯,但在海量数据场景下性能差很多。
架构长这样
微服务 → Filebeat → Kafka(3 broker) → Logstash → Elasticsearch
Kafka在这里的角色就是个缓冲层,削峰填谷。日志高峰期Filebeat疯狂灌数据,Kafka先接住,Logstash慢慢消费往ES里写,不会把ES打挂。
最终效果:500GB/天稳定写入,查询延迟3秒以内,7天自动清理。
这个场景的结论:海量数据 + 高吞吐 + 需要回溯,Kafka是唯一选择,没有之二。
场景三:多租户消息路由
背景:一个SaaS平台,有50个租户,每个租户的消息需要路由到不同的队列,不同租户之间完全隔离。部分租户需要消息优先级,高优先级的先消费。
这个场景,Kafka和RocketMQ都差点意思,RabbitMQ直接起飞。
为什么?
因为RabbitMQ的Exchange路由模型就是干这个的。
我们的架构:
生产者 → Exchange(topic模式)
├── RoutingKey = tenant_A.high → Queue_A_High(高优先级)
├── RoutingKey = tenant_A.normal → Queue_A_Normal
├── RoutingKey = tenant_B.high → Queue_B_High
└── ...
每个租户一个Queue组,互相完全隔离。优先级靠多个Queue实现------消费者先消费高优先级Queue,消费完了再消费普通Queue。
Kafka能不能做?能,但你得自己建50个Topic,每个Topic一个分区。然后消费者那边自己写路由逻辑,判断消息属于哪个租户,再分发到不同的处理线程。这不是不能做,但维护成本高得离谱。50个租户变成500个呢?你的Topic数量直接爆炸。
RocketMQ呢?RocketMQ的Tag机制可以做租户隔离,但优先级队列的支持没有RabbitMQ灵活。RocketMQ的优先级是全局的,不是每个租户独立的优先级,这个需求满足不了。
RabbitMQ的优势在这个场景被拉满了:
| 需求 | Kafka | RocketMQ | RabbitMQ |
|---|---|---|---|
| 多租户路由 | 手动建Topic,维护成本高 | Tag可以做,但不够灵活 | Exchange路由,原生支持 |
| 租户间隔离 | Topic级别隔离,可以 | Queue级别隔离,可以 | Queue级别隔离,可以 |
| 优先级队列 | 不支持 | 支持但不灵活 | 支持,每个队列独立 |
| QPS要求 | 不高,500QPS | 不高 | 完全够用 |
最终效果:50个租户稳定运行,优先级调度准确,路由规则改了直接在管理后台配,不用改代码。
这个场景的结论:路由逻辑复杂 + QPS不高 + 需要优先级,RabbitMQ是最优解。
所以到底怎么选?
别再背参数,对着场景选:
| 你的场景 | 选谁 | 核心理由 |
|---|---|---|
| 日志采集、大数据管道、事件溯源 | Kafka | 吞吐天花板,回溯能力强 |
| 订单异步、支付通知、需要消息不丢 | RocketMQ | 事务消息+死信队列+消费回溯,业务功能最全 |
| 多租户路由、优先级队列、协议转换 | RabbitMQ | Exchange路由模型无敌,灵活度最高 |
| 吞吐量10万+,数据要存很久 | Kafka | 磁盘成本低,RocketMQ存不了这么多 |
| 吞吐量1万以下,但业务逻辑复杂 | RabbitMQ | 别用Kafka杀鸡,大材小用 |
| 吞吐量1~5万,需要可靠投递+业务功能 | RocketMQ | 这个区间RocketMQ性价比最高 |
最后说几句
很多人选MQ就看"谁的star多""谁的性能高",这是学生思维。
生产环境的选型,从来不是选最强的,是选最合适的。
Kafka再快,你一个订单系统用它,消息丢了你赔得起吗?RabbitMQ再灵活,你拿它做日志采集,500GB/天它接得住吗?
想清楚你的业务最不能容忍什么:
- 不能丢消息 → RocketMQ
- 不能慢 → Kafka
- 不能路由错 → RabbitMQ
把这个想明白了,选型就不会错。