先说个可能有点反直觉的结论:选MQ这件事,真正难的从来不是“哪个功能多”,而是“你到底要解决什么问题”。我把同一套消息队列方案从日志管道搬到订单交易场景,线上直接丢过消息;也在本该用流式管道的项目里硬塞了RabbitMQ,结果堆积到几十个G,消费者追到天亮都追不上。这些坑回头来看,全是选型阶段埋下的。这篇文章不打算做那种罗列特性的百科式对比,而是按我自己在项目里实际踩过的坑,把常用消息队列(MQ)的核心差异、适用边界、选型判断路径一次讲透,适合正在做技术选型、或者刚接手一个消息中间件需要评估现状的工程师参考。
1. 为什么都是“消息队列”,设计思路却天差地别
很多刚接触分布式系统的同学会以为,所有的MQ本质上都一样:生产者发消息,消费者收消息,中间有个东西存一下。这么理解不算错,但如果带着这个认知去选型,基本一定会踩坑。因为“队列”这个词背后,其实藏着两套完全不同的存储模型。
1.1 队列模型与日志模型:先搞清楚你用的是“容器”还是“管道”
RabbitMQ这类产品,底层就是经典的队列模型:消息进来之后,按顺序放到一个队列容器里,消费者拉走一条就少一条,消息消费完之后就删掉了。这种模型非常直观,就像货架上的商品,拿一件少一件。
Kafka则完全不是这个思路。它底层的核心抽象是“日志”——一个只追加写的有序文件序列。消息写进去之后并不会被删掉,而是靠offset(偏移量)记录消费者读到了哪里。消费者像看视频一样,拖到哪个位置就从哪个位置接着看。同一个消息,你让十个消费者组各读一遍都没问题,因为这只是十个不同的进度指针而已。
RocketMQ介于两者之间。它用类似日志的CommitLog做统一存储,但逻辑上仍然以队列(Topic下的MessageQueue)为单位组织消息,消费完的消息在逻辑上算是“被取走”了,不过物理文件不会立刻删除,而是保留一段时间。这个设计让它既能承接业务消息的语义,又能扛住比较大的堆积。
这就要命了:如果你把Kafka当成一个业务消息队列来用,你会发现在“消费后删除”这个业务语义上,它根本不对味。反过来,如果你把RabbitMQ当成海量日志管道来用,消息堆积到一定程度,性能会直接崩掉,因为它处理堆积的方式是流式分页到磁盘,根本不是为了长周期保留数据设计的。
1.2 独立服务与嵌入式库:ZeroMQ这种“MQ”根本不在同一赛道
还有个容易混淆的点,就是ZeroMQ。很多文章把ZeroMQ和RabbitMQ、Kafka放在一张表里对比,这其实不公平。ZeroMQ不是一个消息中间件服务,它只是一个高性能网络通信库,形态上是一堆你可以嵌入到程序里的socket封装。它没有独立的broker进程,消息不落盘,消费者不在线消息就直接丢。
所以ZeroMQ适合的场景是:你已经知道对端在线,而且就在同一局域网内,需要极低延迟传递大量小消息。比如量化交易系统内部的行情分发,或者游戏服务器集群内的战斗事件同步。它的延迟可以做到微秒级别,而任何带broker的MQ都做不到这个量级。但是,“不丢消息”“消息堆积”“消费者不在线也能收到”这些需求,它一个都给不了你。不是它差,是它压根不需要回答这些问题。
1.3 推模型与拉模型:消费方式决定了你能扛多大的量
还有一个很少被人提起但特别影响选型的差异——消费者到底是被推着走,还是自己主动来拉。
RabbitMQ是典型的推模型(实际上内部是消费者轮询拉取,但broker有流量控制,语义上接近推),broker会把消息主动投递给消费者,投递成功就认为消息处理完了。这种方式的好处是消费及时,消息一进来就能触发处理逻辑,非常适合业务系统里那种“有新订单就马上通知下游”的场景。坏处是消费者处理不过来的时候,broker的压力会变大,需要靠QoS等机制做背压控制。
Kafka是彻底的拉模型,消费者根据自己的处理能力决定什么时候来拉多少条。这样broker完全不用考虑“推太快导致消费者崩溃”的问题,只需要扮演一个被读取的大文件就好了。这是Kafka能支撑百万级吞吐的重要原因之一。但代价就是消费链路天然会有一定的延迟波动,而且“秒级触发”这种体验需要依赖轮询频率来保证。
了解了这几条底层差异,再去看网上那种“RabbitMQ vs Kafka”的争论,很多其实争的根本不是同一个维度的问题。
2. 逐个拆解主流MQ:各自的“性格”与适用边界
每个MQ产品的设计初衷,决定了它面对不同场景时的擅长与偏科。我按实际项目里最常见的几类选择,逐个说说它们的脾气。
2.1 RabbitMQ:业务系统里的可靠信使,但不要让它扛海量堆积
RabbitMQ出身金融领域(最早是华尔街的交易系统在用),天生就把“可靠投递”和“灵活路由”放在第一位。它最核心的武器是Exchange路由模型:生产者不需要把消息直接发到某个队列,而是发到交换机,交换机按照绑定规则(direct、topic、fanout、headers)把消息分发给一个或多个队列。这套机制在业务系统里极为顺手——比如支付成功事件,同一个消息既进订单服务队列,又进积分服务队列,还进短信通知队列,靠着交换机绑定关系,一条消息四处分发,代码干净得让人感动。
Erlang写的运行时,并发模型天生适合做高连接数的消息分发,单机几万连接都没什么问题。延迟能做到微秒级到毫秒级,可靠性靠生产者确认、消费者手动ack、持久化队列三层机制,不给中间商留太多丢消息的机会。
但它的短板也很清楚:堆积能力弱。RabbitMQ把消息优先放内存,堆到一定阈值开始分页写磁盘,这个处理方式决定了一个队列如果长期积压几十万上百万条消息,性能会显著恶化。另外Erlang技术栈在国内相对小众,出了问题排查成本高。我见过一个团队用RabbitMQ处理日志,消息量一上来直接拖垮节点,最后运维同学被迫用一堆脚本做应急清理。
适合:业务系统内部模块间的事件通知、任务分发、需要灵活路由和复杂ACK语义的场景。不适合:日志管道、海量流式数据、需要长时间大容量堆积的离线场景。
2.2 Kafka:海量日志与流式管道的王者,但别把它当业务MQ用
Kafka是LinkedIn为了解决日志收集问题搞出来的,底层设计目标只有一个:写入和读取都要尽量地快。它把顺序写盘、页缓存、零拷贝、批量发送这些技巧全用上了,单机吞吐就能顶到百万条每秒级别。配合分区并行,集群吞吐基本可以线性扩展。
可以说,Kafka最擅长的就是“堆积”:消息在磁盘上以segment文件存在,保留几天的数据毫无压力。因为有offset机制,消费者可以反复从头读,掉线的消费者重启后可以从上次的位置续读,甚至可以做时间回溯。这在数据管道场景里简直完美:应用日志、埋点、数据库binlog同步、流式计算(Flink上游),全都是Kafka的主场。
但Kafka的代价也明显。它天生不擅长复杂路由——你把消息发进一个topic,所有消费者组都只能按这个topic来读,没有交换机那种按业务规则定向分发的概念。想要类似“死信队列”的能力,得靠Streams或自己写消费逻辑落库。更麻烦的是,Kafka的可靠性并没有默认拉满,acks=0、acks=1、acks=all分别对应丢消息、broker崩溃可能丢、副本同步后才确认。很多团队图省事直接默认配置,等到线上broker重启才发现消息丢了。它不是不能保证不丢,是“保证不丢”需要你认真配置副本数、ISR参数,还需要接受写入延迟和吞吐的一定牺牲。
适合:日志聚合、大数据管道、流式计算、事件溯源、需要消息回溯的离线场景。不适合:延迟敏感的同步业务调用、复杂消息路由、需要死信策略支撑的业务系统。
2.3 RocketMQ:为电商业务而生的可靠消息中间件
RocketMQ是阿里在淘宝内部消息中间件演进过程中逐步开源出来的,定位非常清晰:既要高吞吐,又要业务级可靠,还要解决分布式事务问题。在“业务消息”这个赛道上,它的设计几乎是考虑得最周全的。
它用Java重写了Kafka那套日志模型,吞吐量虽然略逊于Kafka的极限压测数据,但在十万级到几十万级每秒这个区间,对付绝大多数业务系统的流量绰绰有余。它的可靠性和可用性设计比Kafka更“偏向业务”:同步刷盘、异步刷盘、同步复制、异步复制可以按队列级别配置,Broker崩溃恢复机制也比早期Kafka成熟得多。更关键的是两大杀手锏:事务消息和延时消息。
事务消息解决的是“本地数据库操作和发消息不能保证原子性”的经典难题。RocketMQ的半消息机制让生产者先把消息发给broker但不让消费者看见,等本地事务执行成功后再提交,如果提交失败还能走回查。这在订单创建、余额变更这种必须保证“数据要么都成功要么都不成功”的场景里,几乎是刚需。延时消息则是原生支持18个级别的延迟投递,比如订单超时未支付自动关闭,直接用延时消息做,不用再拿Redis搞一套定时任务轮询。
欠缺的地方也有:文档和社区生态相对Kafka要窄一些,集群部署和运维指南的成熟度略逊,性能压测数据虽然好看,但真正大规模踩坑的经验沉淀没有Kafka那么丰富。
适合:核心业务链路中的消息通信、需要事务消息和延时消息的场景、中大规模吞吐+高可靠并重的场景。不适合:纯日志管道(用它做日志确实有点浪费,又比Kafka重)、极端追求吞吐的离线数据场景。
2.4 ActiveMQ与IBM MQ:经典企业级选手的现状
ActiveMQ是JMS规范最早的开源实现之一,Java体系里的老前辈。它最大的价值是“标准”:如果你所在的系统强依赖Java/J2EE,团队习惯JMS那套API语义,ActiveMQ能无缝接入。但坦白讲,它的吞吐量在万级以内,堆积能力一般,性能和运维便利性比RocketMQ差一大截。现在新项目如果再选型,我基本不建议再选它,更适合用来维护存量系统。
IBM MQ则是企业级商业MQ的标杆,在金融、政府、军工这类对稳定性和合规性要求极高的场景中仍然有大量存在。它的优势不是性能跑分,而是几十年积累的可靠性、消息完整性、安全认证体系,以及商业公司的兜底支持。但价格昂贵、部署运维门槛高,如果你不是在一个合规约束极强的行业里做系统,大概率用不上它。
2.5 Pulsar和BMQ:云原生时代的新势力,值得列入候选
Pulsar和百度开源的BMQ(以及相关云产品)代表了另一个方向:存算分离。Kafka的痛点在于broker同时承担存储和计算,扩容时数据要跟着迁移,重平衡期间集群会有明显的抖动脉冲。Pulsar把消息存在独立的BookKeeper集群里,broker只做调度,扩容时不用搬数据。BMQ更是把ZooKeeper这个核心依赖都给干掉了,直接基于BookKeeper做元数据管理,架构上更简洁。
这类产品最大的好处是弹性:扩容缩容都很快,存储成本也更可控,特别适合云原生环境。但它们在业界的成熟度和生态建设(组件、监控、运维经验)还不如Kafka和RabbitMQ那么厚,遇到疑难杂症可参考的资料少。我的判断是:如果团队对存算分离有明确需求,且有足够的中间件运维能力,可以把Pulsar/BMQ放进候选池;如果只是想找一个稳妥的生产方案,Kafka和RocketMQ仍然更保险。
3. 关键指标横评:吞吐、延迟、可靠性、堆积与运维
横评表格网上到处都是,但光给一个数字没有意义,得说清楚数字背后的代价和适用条件。先上总表,再逐项拆解。
| 维度 | RabbitMQ | Kafka | RocketMQ | ActiveMQ | ZeroMQ |
|---|---|---|---|---|---|
| 模型定位 | 队列模型 | 日志模型 | 日志+队列混合 | 队列模型 | 通信库 |
| 单机吞吐量 | 万级/秒 | 百万级/秒 | 十万级~数十万级/秒 | 万级以下/秒 | 百万级(库内) |
| 典型延迟 | 微秒~毫秒级 | 毫秒级 | 毫秒级 | 毫秒级 | 微秒级 |
| 消息堆积能力 | 弱 | 极强 | 强 | 弱 | 无 |
| 路由能力 | 极强(Exchange) | 弱 | 中(Tag/过滤) | 强 | 无(模式固定) |
| 可靠性保障 | 强(确认+持久化) | 依赖配置 | 强(同步复制) | 中 | 无 |
| 事务消息 | 无(近似实现) | 有(成本高) | 有(半消息) | 支持XA | 无 |
| 时序保障 | 单队列有序 | 分区内有序 | 队列内有序 | 单队列有序 | 无 |
| 运维复杂度 | 中(Erlang排查偏难) | 高(ZK/rebalance坑多) | 中(Java系好处理) | 低 | 极低(无服务) |
3.1 吞吐量与延迟:这个“两难”是底层存储决定的
吞吐量为什么差这么多?核心在写路径。Kafka敢说自己百万级吞吐,靠的是顺序写文件——消息进来直接append到磁盘末尾,磁盘顺序写的速度远高于随机写。再加上页缓存做缓冲,生产者批量发送,一次网络包塞几百条消息,IO效率极高。RabbitMQ则不同,它的队列是内存优先,遇到底层持久化时涉及到随机写盘(不同队列不同消息散落在不同文件位置),拿自然规律换吞吐,这个差距没法单靠调参数抹平。
延迟则又反过来。吞吐高的系统为了批量化,往往要在攒一批消息和等待网络轮询之间做个平衡,单条消息的“端到端延迟”就会波动。RabbitMQ这种推风格的模型,消息一到就通知消费者,单条延迟基本就是网络+RTT,几乎无额外开销。你永远无法同时拿到极致吞吐和极致单条延迟,选型时先把这两个指标的优先级排序定了,再去看产品就清楚多了。
3.2 可靠性:三种保障级别,先想清楚你要哪一种
绝大部分选型冲突,本质上是“不同级别的可靠性取舍”冲突。消息可靠性一般分三档:
- 最多一次(at-most-once):发送或消费过程中消息可以丢,但绝不重复。适合日志采集、监控上报这种丢了还能从源头重采的数据。
- 至少一次(at-least-once):消息尽量不丢,但可能重复消费。业务系统绝大多数选这一档,因为幂等处理比消息丢失好扛——消费端做个去重表、状态机校验,重复了也没关系。
- 精确一次(exactly-once):既不丢也不重复。这是最贵的一档,需要在生产端幂等、broker端精确存储、消费端事务性提交三者协同,代价是性能和复杂度。
Kafka的幂等生产者和事务API可以实现分区级别的精确一次,但配置复杂,还会压低吞吐。RocketMQ的事务消息解决的是“本地事务和消息发送的原子性”,跟消费端的精确一次又是两回事。RabbitMQ没有原生事务消息,只能靠发布者确认+消费方手动ack近似实现“不丢”,但本地事务跨MQ的原子性得自己拿方案(比如本地消息表)。选型前务必先把这个可靠性级别定了,因为这是后续所有配置的前提。
3.3 堆积能力与回溯能力:Kafka的护城河
Broker重启时,RabbitMQ往往有大量消息在内存中等着持久化,一旦进程被强杀就凉了。Kafka则几乎时刻都在把段文件写盘,而且数据保留多久可以配置,消费者无论是掉线几天还是需要重头消费,offset都能指回去。RocketMQ虽然消费后逻辑上删除,但物理文件默认保留72小时,可以靠定时任务重建消费位点。对于需要数据重放和故障复盘的系统,回溯能力至关重要。做数据管道时,P95延迟抖动导致消费端跑挂,靠Kafka的offset回溯就能快速恢复;换成RabbitMQ,消费完的消息说没就没,复盘就只能依赖日志和数据库流水了。
3.4 运维复杂度:选择一种“你团队养得活”的方案
运维往往是选型时最被低估的一环。Kafka集群要维护ZooKeeper(或KRaft模式,新版本已经好一些),调优参数极多,分区分片重平衡一有问题就是深夜告警。RabbitMQ本身运维轻,但一旦遇到性能瓶颈,排查Erlang运行时和内核参数会让你怀疑人生。RocketMQ用Java写的,出问题能抓thread dump,团队有Java基础基本能扛住。ZeroMQ压根没有broker,运维成本为零,但你得自己负责所有断线、重连、丢消息的逻辑。选型时务必问一句:这个产品将来出了问题,我们团队有没有能力处理。
4. 选型方法论:一套可直接套用的决策路径与避坑清单
看了这么多差别,落到实际项目里怎么选?我习惯用一套漏斗式的决策路径,从粗到细,避免被产品营销影响带偏。
4.1 五步决策路径
第一步,估算消息量和峰值速率。这是硬门槛,直接决定了你能不能碰RabbitMQ。如果你现在的日均消息量在百万到千万级,峰值为每秒几千到几万条,RabbitMQ能轻松对付。如果你要做日志管道,日增几十亿条、峰值每秒几十万条,RabbitMQ直接出局,Kafka或RocketMQ二选一。
第二步,判断路由需求。你的场景是不是需要“一条消息按规则分发给不同下游”?如果订单事件要同时触发库存、积分、短信、审计,还想按优先级分流,RabbitMQ的Exchange是天选之子。如果所有消费者关心的就是同一个Topic的流式数据,那Kafka/RocketMQ的Topic模型已经覆盖,没必要引入复杂的交换机层。
第三步,确认可靠性和事务需求。系统涉及扣款、订单状态流转,生产者本地事务和发消息必须一致,那就看RocketMQ的事务消息。没有强一致事务需求但关键链路不能丢,RabbitMQ的发布者确认+手动ACK足够。数据管道型的系统,丢几条日志无所谓还是绝不能丢?前者选Kafka默认配置能省很多事,后者就得按Kafka高可靠配置来维护。
第四步,评估团队语言栈和运维能力。Java团队上手RocketMQ最顺;Erlang对大多数人都是黑盒;Kafka生态成熟但运维深坑多。零运维预算的团队,选托管云产品(云上的RabbitMQ或Kafka托管集群)比自建更实际。
第五步,对齐公司已有基建。如果公司已经有统一的Kafka集群和成熟的Topic治理规范,新业务优先复用,除非业务特性与Kafka模型确有严重冲突,否则不要轻易为了“功能多”而引入一套新中间件。中间件每多一种,运维成本是翻倍叠加的。
4.2 真实踩坑案例:选错的代价
案例一,把日志管道塞进RabbitMQ。团队不想引入Kafka觉得重,用RabbitMQ的fanout交换机收集应用日志,刚开始日均几千万条还能扛,上线三个月后队列堆积冲到几十个G,消费者追不上,节点频繁报警。最后没办法,连夜写Kafka迁移方案,中间还丢了两天的日志数据。我不是说RabbitMQ不能做日志,但你要清楚它能承受的堆积量级是有上限的,长周期海量堆积必须换引擎。
案例二,用Kafka扛交易核心链路。另一个团队觉得Kafka吞吐高就用它做订单消息,结果线上Broker重启时,由于部分分区副本数配置不当+acks没有设all,重启丢了小几十条订单消息,业务方核对账目时才发现。技术总监连夜复盘,最终把交易链路迁到了RocketMQ。Kafka吞吐确实强,但这个强是用“最终一致”的逻辑换来的,强一致交易场景最好绕开。
案例三,为了“延迟消息”硬用Redis+定时轮询。这个不算选错MQ,而是没认真看中间件能力。后来换RocketMQ,原生延时消息一发,定了18个延时级别,业务方只需要选择一个级别,立刻省掉了一套轮询系统。选型的时候别只顾着比吞吐,把你能想到的“未来三个月功能需求清单”也翻出来。
5. 容易被忽视但影响深远的机制差异:顺序性、幂等消费与消费状态
很多人在选型时只关注吞吐和延迟,上了线才被“顺序”“重复消费”“消息回溯”这几个问题坑到。这些机制层面的差异,对系统健壮性的影响比大多数指标都深远。
5.1 消息顺序:分区内有序不等于全局有序
Kafka的顺序保证是分区级别的:同一个key(比如订单ID)会被路由到同一个分区,分区内消息顺序严格保持,跨分区之间没有全局顺序。RocketMQ也类似,同一个MessageQueue内有序。RabbitMQ单队列内有序,但如果你有多个消费者并发拉取同一个队列,顺序就会被打乱(除非用单消费者+手动确认串行处理)。ZeroMQ压根不保证顺序。
实际工程里,全局顺序是真的难。假设有一个“订单状态更新”业务,要求所有消息严格按时间顺序处理。你用Kafka单分区可以做到严格顺序,但吞吐量被卡死在一个分区的写入能力上。想要高吞吐就得分区,分区就分不了严格全局顺序。这种场景我一般建议:从业务上寻找天然的分区键(订单维度、用户维度、店铺维度),把顺序约束收敛到同一个key内部,比追求全局有序要现实得多。
还有一点,Kafka的rebalance发生时,消费组会暂停所有分区消费,等待分区再分配完成。如果消费逻辑比较重,每次rebalance都会带来明显的处理空窗期——这一点在给消费端做故障恢复时容易背锅。RocketMQ也有重平衡但机制更温和,RocketMQ的ReBalance逻辑不会让整个消费组停下来,而是单独处理变化的分区。
5.2 重复消费与消费状态:到底谁来记这个进度
重复消费几乎是MQ世界里无解的宿命。网络超时后重发、消费端处理完消息但ACK丢了、消费端收到消息后宕机,任何一个环节都会造成重复。所以工程上的真正解法不是“拼命不重复”,而是消费端做幂等处理:唯一键唯一约束、状态机校验、Redis/DB去重表,三选一。
消费进度的保存方式也决定了你能处理多复杂的故障。Kafka的offset存broker端,消费组提交一次更新一次;RabbitMQ的ACK存在队列里,消费完就没了;RocketMQ的消费位点存Broker也能存客户端本地。差异主要体现在回溯上:Kafka因为offset都在,随时可以把消费者回拨到任意历史位置重新消费,这在故障恢复和补数时是救命级能力。RabbitMQ需要靠插件和额外日志才能实现类似能力,复杂度高得多。
5.3 事务消息与本地消息表:RocketMQ为什么省心
拿订单服务举例,最经典的问题是:先写DB还是先发消息?先发消息,DB回滚了,消息却已经告诉别人“订单创建成功”;先写DB,然后发消息失败,下游永远不知道有新订单。
RocketMQ的事务消息机制解决得很完整。发送半消息给broker,broker存储但不让消费者可见;本地事务成功执行,提交确认;本地事务失败,回滚掉的半消息也就没有消费者能看到。万一提交确认因为网络原因丢了,broker会反向回查生产者的本地事务状态,保证最终一致性。这个“回查”机制是RocketMQ特有的,用起来感觉就是:“我把核心链路的数据库操作和消息发送包在一个逻辑事务里了”。
Kafka的幂等生产者和事务API也能做类似的事情,但是它的实现要求把事务协调(Transaction Coordinator)打开,对客户端和broker的配置要求都更敏感,工程上费心得多。RabbitMQ没有这个机制,只能用本地消息表+定时任务扫描补发,代码写起来很绕。所以只要有强一致事务需求的业务系统,我的第一选择永远是RocketMQ。
5.4 死信与重试策略:业务消息里最容易被低估的功能
RabbitMQ原生支持死信队列(DLX),消息消费失败可以路由到死信交换机做后续处理,这是它在业务场景里舒服的重要原因之一。RocketMQ的消息重试和死信队列机制也完备,批处理消费失败后自动按等级重试,重试还失败就进死信Topic。Kafka在这一块几乎是缺失的:没有原生的重试队列、死信队列,需要自己写消费端逻辑,把失败消息再发回原Topic或专用Topic。做业务系统时,如果团队经验一般,“消费失败的消息去哪了”这个问题非常容易变成事故现场,选型时千万别忽略这个对业务细节的支撑能力。
6. 最后说点实在的:按这个表单做决策,基本不会翻车
这些年选型做过太多次,也推翻过太多次,踩过的坑比总结过的经验还多。现在我的习惯是,不管宣传材料里写什么架构神话,回到办公室先对着这张表单打勾:
- 数据量级:当前和未来一年内的峰值消息速率大概多少?单机万级还是十万级还是百万级?
- 数据性质:这些消息是生命周期短暂的业务事件,还是要长期留存、可回溯的数据流?
- 消费方式:下游需要比较及时的推送通知,还是可以自己按节奏批量拉取?
- 一致性要求:本地事务和发消息之间,能不能接受短暂的不一致?
- 顺序要求:业务上必须严格按某个粒度串行处理吗?顺序约束能不能收敛到某个key?
- 运维现实:这个团队有几人会被MQ问题半夜叫醒?他们最熟的中间件是什么?
- 平台约束:公司有没有已经规模化的消息集群?新的中间件需要走多长的审批和审计流程?
把这七项全部过完,答案多半已经浮出水面了,不需要再去比较各种花哨的特性术语。至于那些一上来就让你“必须用某款MQ”的意见,不管是同事还是供应商说的,都先放一放——他一定没有在你这个具体场景里踩过坑。
我个人在不同阶段的选择偏好也仅供你参考:做日志管道和大数据链路,我倾向Kafka,它皮实、能回溯、吞吐大;做核心交易、订单状态、事务型业务,我倾向上RocketMQ,尤其有事务和延时需求的时候;做分布式系统内部的事件分发与任务解耦,RabbitMQ仍然是那种“最省心”的选择。最后再啰嗦一句,选型不是一锤子买卖,中间件演进很快,隔一年回访一次当时的假设是否还成立,比一开始追求“一步到位”要有用得多。