第二章:主流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 选型建议:到底怎么选?
这个问题没有标准答案,但我可以给你一个「决策树」:
- 先看业务场景:如果是日志、埋点、流式计算,直接上 Kafka。别犹豫。
- 再看路由需求:如果消息需要复杂的路由策略(比如根据消息内容分发到不同队列),选 RabbitMQ。
- 再看可靠性要求:如果涉及资金、订单,需要事务消息,选 RocketMQ。
- 最后看团队能力:如果团队对 Java 栈熟悉,RocketMQ 和 Kafka 都行。如果团队偏运维,RabbitMQ 更友好。
我的个人建议:新项目首选 Kafka 或 RocketMQ。RabbitMQ 适合做「消息路由网关」,ActiveMQ 除非是遗留系统,否则别碰。记住,选型不是选「最好的」,而是选「最合适的」。
好了,这一章的内容就到这里。下一章我会深入 RabbitMQ 的核心机制——Exchange 和 Binding,带你看清楚消息到底是怎么「跑」起来的。