第二章:主流MQ对比——RabbitMQ、Kafka、RocketMQ、ActiveMQ的架构与选型

说实话,每次有新人问我「到底该选哪个消息队列」,我都觉得这是个好问题,也是个坑。好在哪里?选对了,后面几年都省心。坑在哪里?很多人一上来就比性能、比吞吐量,结果忽略了业务场景。

我个人习惯是,先看架构,再看场景,最后才看数字。今天我就把这四个主流MQ的底裤扒一扒,聊聊它们的架构差异和选型逻辑。

2.1 RabbitMQ:老牌劲旅,专治各种「复杂路由」

RabbitMQ 是我最早接触的消息中间件。记得2015年我第一次用它做订单系统,当时被它的 Exchange 机制搞得晕头转向。后来用顺手了,才发现这东西是真的灵活。

架构核心

  • Broker:消息中转站,一个 RabbitMQ 实例就是一个 Broker
  • Exchange:交换机,消息进来的第一站。它不存消息,只负责路由
  • Queue:队列,消息真正落脚的地方
  • Binding:绑定关系,把 Exchange 和 Queue 连起来

说白了,RabbitMQ 的核心思想就是「消息先到 Exchange,Exchange 根据规则把消息扔到对应的 Queue 里」。这个规则有四种:Direct、Topic、Fanout、Headers。

我踩过的坑:曾经有个项目,同事把 Fanout Exchange 当 Direct 用,结果消息广播到所有队列,下游服务全炸了。嗯,选对 Exchange 类型真的很重要。

适用场景

  • 需要灵活的路由策略(比如根据消息类型分发到不同队列)
  • 对延迟敏感的场景(RabbitMQ 的延迟通常在微秒级)
  • 中小规模系统(单机吞吐量在万级/秒)

2.2 Kafka:流式王者,专为高吞吐而生

Kafka 的设计哲学跟 RabbitMQ 完全不同。它从一开始就是为「日志收集」和「流式处理」设计的。你想想看,如果每天要处理几十亿条日志,RabbitMQ 那套 Exchange 机制就太「重」了。

架构核心

  • Producer:生产者,往 Topic 里写消息
  • Consumer:消费者,从 Topic 里读消息
  • Topic:主题,消息的逻辑分类
  • Partition:分区,Topic 的物理分片。这是 Kafka 高吞吐的关键
  • Broker:集群中的节点

Kafka 的牛逼之处在于:一个 Topic 可以拆成多个 Partition,每个 Partition 可以分布在不同的 Broker 上。这样读写就能并行,吞吐量轻松上百万/秒。

我的经验:Kafka 的 Partition 数量不是越多越好。我见过有人把 Partition 设到 1000 个,结果 Rebalance 一次要半小时。建议 Partition 数不超过 Broker 数的 10 倍。

适用场景

  • 日志收集、埋点数据、监控指标
  • 流式处理(配合 Flink、Spark Streaming)
  • 需要消息回溯、重放(Kafka 默认保留所有消息 7 天)

2.3 RocketMQ:阿里出品,国产之光

RocketMQ 是阿里巴巴开源的,脱胎于 Kafka,但做了很多「接地气」的改进。我在做电商项目时用过它,感觉它把 Kafka 的「短板」都补上了。

架构核心

  • NameServer:注册中心,类似 Kafka 的 Zookeeper,但更轻量
  • Broker:消息存储节点,分为 Master 和 Slave
  • Producer:生产者
  • Consumer:消费者,支持 Push 和 Pull 两种模式

RocketMQ 跟 Kafka 最大的区别是:它支持事务消息和延迟消息。Kafka 在这块几乎是空白,而 RocketMQ 做得相当成熟。

注意:RocketMQ 的延迟消息只支持 18 个固定级别(1s、5s、10s、30s...),不支持自定义延迟时间。我曾经因为这个踩过坑,后来改用定时任务绕过去了。

适用场景

  • 电商交易系统(订单、支付、库存)
  • 需要事务消息的场景(比如「下单后必须发消息」的强一致性需求)
  • 金融、对账等要求高可靠性的场景

2.4 ActiveMQ:老将迟暮,但仍有江湖

ActiveMQ 是 Apache 的老牌 MQ,JMS 规范的参考实现。说实话,现在新项目很少用它了,但很多遗留系统还在跑。我去年帮一个银行客户迁移系统,就遇到了 ActiveMQ 5.x 的老项目。

架构核心

  • Broker:消息代理,支持嵌入式和独立部署
  • Destination:目的地,分为 Queue(点对点)和 Topic(发布订阅)
  • Message:消息体,支持多种类型(TextMessage、ObjectMessage 等)

ActiveMQ 最大的问题是性能瓶颈。单机吞吐量大概在万级/秒,跟 Kafka 比差了两个数量级。而且它的集群方案(Network of Brokers)配置复杂,脑裂问题时有发生。

避坑指南:我曾经遇到 ActiveMQ 在高并发下消息丢失的问题。后来查了半天,发现是默认的异步发送配置导致的。如果你非要用 ActiveMQ,记得把 useAsyncSend 设为 false。

适用场景

  • 遗留系统的维护和升级
  • 对吞吐量要求不高的内部系统
  • 需要 JMS 标准兼容的场景

2.5 四款MQ核心对比

维度 RabbitMQ Kafka RocketMQ ActiveMQ
开发语言 Erlang Scala/Java Java Java
协议支持 AMQP、MQTT、STOMP 自定义TCP协议 自定义协议 OpenWire、STOMP、AMQP
吞吐量 万级/秒 百万级/秒 十万级/秒 万级/秒
延迟 微秒级 毫秒级 毫秒级 毫秒级
消息可靠性 高(支持Confirm、事务) 高(支持ACK、副本) 高(支持同步刷盘、副本) 中(默认异步发送)
路由灵活性 极高(4种Exchange) 低(仅Topic) 中(Tag过滤) 中(Selector过滤)
运维复杂度 中(需管理ZK) 中(需管理NameServer)
社区活跃度 极高

2.6 选型建议:到底怎么选?

这个问题没有标准答案,但我可以给你一个「决策树」:

  1. 先看业务场景:如果是日志、埋点、流式计算,直接上 Kafka。别犹豫。
  2. 再看路由需求:如果消息需要复杂的路由策略(比如根据消息内容分发到不同队列),选 RabbitMQ。
  3. 再看可靠性要求:如果涉及资金、订单,需要事务消息,选 RocketMQ。
  4. 最后看团队能力:如果团队对 Java 栈熟悉,RocketMQ 和 Kafka 都行。如果团队偏运维,RabbitMQ 更友好。

我的个人建议:新项目首选 Kafka 或 RocketMQ。RabbitMQ 适合做「消息路由网关」,ActiveMQ 除非是遗留系统,否则别碰。记住,选型不是选「最好的」,而是选「最合适的」。

好了,这一章的内容就到这里。下一章我会深入 RabbitMQ 的核心机制——Exchange 和 Binding,带你看清楚消息到底是怎么「跑」起来的。