Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← Web 开发 / Web Development

中间件 / Middleware

1. Web 中间件全景 / The Web Middleware Landscape

2. 中间件——流量洪峰下的系统保护 / Middleware for Protecting Systems Under Traffic Spikes

cache layer

1. 缓存架构全景 / Cache Architecture Overview

2. Redis 深入——为什么你的缓存总是出问题 / Redis Internals and Cache Failure Modes

3. Redis 数据结构场景应用——什么时候用什么 / Choosing Redis Data Structures for Real Applications

4. 缓存策略——库存变了,缓存怎么处理 / Cache Strategies and Inventory Consistency

5. Redis 缓存三剑客——穿透/击穿/雪崩 + 一致性策略 / Redis Cache Penetration, Breakdown, Avalanche, and Consistency

6. Redis 分布式锁——从 SETNX 到 Redisson / Redis Distributed Locks from SETNX to Redisson

7. Redis Cluster 与 Sentinel 高可用架构 / Redis Cluster and Sentinel High-Availability Architecture

8. Redis 高级特性——Stream / PubSub / Module / LLM 应用

9. Redis 架构深度分析——为什么 Redis 能这么快 / Redis Architecture and the Sources of Its Performance

10. Redis 全景——为什么你的系统需要一个缓存层 / The Redis Landscape and Why Systems Need a Cache Layer

message queue

1. 消息队列全景——为什么你的系统需要一个中间人 / Message Queue Overview and Why Your System Needs a Middleman

2. Kafka 核心——为什么你的消息总是"丢"了 / Kafka Fundamentals and Message Delivery Semantics

3. 消息队列高级——死信队列、延迟消息、消息积压 / Advanced Messaging with Dead Letters, Delays, and Backlogs

4. Kafka Streams 与 Connect —— 让数据自己流动起来 / Kafka Streams and Connect for Streaming Data Pipelines

5. RabbitMQ 深度解析 —— 灵活路由与消息可靠性 / RabbitMQ Deep Dive into Flexible Routing and Reliability

6. 消息队列对比——为什么最终选了 Kafka / Comparing Message Queues and Choosing Kafka

search engine

1. 搜索引擎知识体系 / Search Engine Knowledge System

2. Elasticsearch——为什么 Like 查询总是那么慢 / Elasticsearch for Full-Text Search at Scale

3. Elasticsearch 查询 DSL 深入——为什么你的搜索总是不准 / Elasticsearch Query DSL Deep Dive

4. Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations

5. Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives

infrastructure

1. 基础设施组件全景 / Infrastructure Components Landscape

2. Nginx 与反向代理 / Nginx and Reverse Proxy

3. 服务发现 / Service Discovery

4. 配置中心 / Configuration Center

本页目录

消息队列对比——为什么最终选了 Kafka / Comparing Message Queues and Choosing Kafka ​

📅 创建时间:2026-05-08 🏷️ 标签:#RabbitMQ #RocketMQ #Pulsar #消息队列 #选型 #延迟消息 #顺序消息 📚 前置知识:[[00-backend-overview]] [[02-mq-kafka]](Kafka 核心机制) 📚 相关知识:[[04-distributed-system]](分布式事务) [[11-architecture-patterns]](事件驱动)


场景:面试官问你,为什么你们选了 Kafka 而不是 RabbitMQ? ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  面试官:你为什么选 Kafka?                                │
│  面试者:因为...大家都用?                                 │
│  面试官:你们系统日活多少?                                │
│  面试者:5 万。                                            │
│  面试官:那你为什么不选 RabbitMQ?                         │
│  面试者:...                                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10

这一章,我们理解每种 MQ 的设计哲学,以及什么场景选什么。


第1节:四强横评——为什么排队这么久 ​

先问自己三个问题 ​

┌─────────────────────────────────────────────────────────────┐
│              选 MQ 前必须回答的三个问题                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题 1:吞吐量多少?                                      │
│  • 日活 100 万以下 → RabbitMQ / RocketMQ 够用           │
│  • 日活 1000 万以上 → Kafka / Pulsar                      │
│                                                             │
│  问题 2:需不需要严格顺序?                                │
│  • 需要同一用户的操作有序 → Kafka / RocketMQ               │
│  • 不需要 → RabbitMQ / Pulsar 都可以                     │
│                                                             │
│  问题 3:需不需要事务消息?                                │
│  • 扣库存 + 创建订单必须原子 → RocketMQ 事务消息          │
│  • 不需要 → Kafka 幂等生产者足矣                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

第2节:RabbitMQ——"瑞士军刀"式的灵活 ​

核心概念:Exchange + Binding ​

┌─────────────────────────────────────────────────────────────┐
│                 RabbitMQ 路由模型                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Producer ──▶ Exchange(交换机)──路由规则──▶ Queue ──▶ Consumer
│                                                             │
│  Exchange 类型:                                            │
│                                                             │
│  direct: 精确匹配 routing_key → 指定 Queue                 │
│  fanout: 广播 → 所有绑定的 Queue                          │
│  topic:  通配符匹配 (order.*, *.created)                  │
│  headers: 按消息头属性匹配                                 │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  场景:订单状态变化通知                            │  │
│  │                                                     │  │
│  │  Exchange: order.events (topic)                     │  │
│  │                                                     │  │
│  │  order.created    ──▶ Queue: order-created-handlers │  │
│  │  order.paid       ──▶ Queue: order-paid-handlers   │  │
│  │  order.cancelled  ──▶ Queue: order-cancelled-handlers│  │
│  │  order.*          ──▶ Queue: order-all-handlers    │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

RabbitMQ 的优势:灵活路由 ​

python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明交换机
channel.exchange_declare(exchange='order.events', exchange_type='topic')

# 声明队列
channel.queue_declare(queue='order-created-handlers')
channel.queue_declare(queue='order-paid-handlers')

# 绑定:Routing Key → Queue
channel.queue_bind(exchange='order.events', queue='order-created-handlers', routing_key='order.created')
channel.queue_bind(exchange='order.events', queue='order-paid-handlers', routing_key='order.paid')

# 生产者:按不同 routing_key 发到不同队列
channel.basic_publish(
    exchange='order.events',
    routing_key='order.created',  # 只发给 created 处理器
    body=json.dumps({"order_id": 1, "status": "created"})
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

RabbitMQ 的劣势:吞吐量 ​

┌─────────────────────────────────────────────────────────────┐
│              RabbitMQ vs Kafka 吞吐量对比                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  RabbitMQ(单节点):                                      │
│  • 吞吐量:5-10 万条/秒                                    │
│  • 队列个数增加后,性能下降(Erlang 虚拟机瓶颈)          │
│  • 队列存储在内存(可选持久化,但性能下降)              │
│                                                             │
│  Kafka(3 节点集群):                                    │
│  • 吞吐量:100-500 万条/秒                                │
│  • 队列(分区)数增加后,性能稳定                         │
│  • 数据持久化到磁盘(通过 PageCache 加速)                │
│                                                             │
│  为什么差距这么大?                                        │
│  RabbitMQ:队列 = 消费者缓冲区(内存)                    │
│  Kafka:队列 = 磁盘文件(追加写 + PageCache)             │
│                                                             │
│  但:RabbitMQ 的单条消息延迟更低(无磁盘 IO)             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

RabbitMQ 高级特性 ​

1. 消息 TTL ​

python
# 队列 TTL:队列中所有消息超过这个时间自动删除
channel.queue_declare(queue='order.pending', arguments={
    'x-message-ttl': 300000,  # 5 分钟
    'x-max-length': 1000      # 最多 1000 条
})

# 消息 TTL:单条消息的过期时间
channel.basic_publish(
    exchange='',
    routing_key='order.pending',
    body=json.dumps({"order_id": 1}),
    properties=pika.BasicProperties(expiration='60000')  # 60 秒
)
1
2
3
4
5
6
7
8
9
10
11
12
13

2. 死信队列(DLX) ​

python
# 订单超过 5 分钟未支付,自动进入死信队列
channel.queue_declare(queue='order.dlx', arguments={
    'x-dead-letter-exchange': 'order.dlx.exchange',  # 死信交换机
    'x-dead-letter-routing-key': 'order.expired'     # 死信路由键
})
1
2
3
4
5

3. 延迟队列(通过 TTL + DLX 实现) ​

python
# 订单超时未支付:TTL 5分钟 → DLX → 取消订单处理器
# 实际使用:rabbitmq-delayed-message-exchange 插件
channel.queue_declare(queue='order.timeout', arguments={
    'x-delayed-message-type': 'direct',
    'x-delayed': 300000  # 5 分钟后投递
})
1
2
3
4
5
6

第3节:RocketMQ——阿里出品,中国互联网实战 ​

RocketMQ 的独特能力 ​

┌─────────────────────────────────────────────────────────────┐
│              RocketMQ vs Kafka 的核心差异                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Kafka 的问题:                                            │
│  ❌ 消息重复消费:at-least-once 设计                      │
│  ❌ 事务消息:只保证 Kafka 内部,跨数据库不行              │
│  ❌ 延迟/定时消息:不支持                                  │
│  ❌ 消费顺序:一个分区只能一个消费者                       │
│                                                             │
│  RocketMQ 的答案:                                        │
│  ✅ 消息不可重复:天然幂等                                 │
│  ✅ 事务消息:half 消息 + 本地事务 + 回查                 │
│  ✅ 延迟消息:18 个延迟级别(1s-2h)                     │
│  ✅ 顺序消息:按用户维度锁定消费                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

事务消息(核心差异) ​

┌─────────────────────────────────────────────────────────────┐
│              RocketMQ 事务消息原理                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  场景:创建订单(MySQL) + 扣减库存(Redis),必须原子   │
│                                                             │
│  Step 1: 发送 half 消息(预发送)                         │
│  Producer ──▶ RocketMQ ──▶ 返回 ACK(此时消息不可见)    │
│                                                             │
│  Step 2: 执行本地事务(MySQL + Redis)                   │
│  Producer 执行:INSERT orders; Redis.decr(stock);          │
│                                                             │
│  Step 3a: 本地事务成功 → 提交 half 消息                   │
│  Producer ──▶ RocketMQ: commit ──▶ 消息对消费者可见      │
│                                                             │
│  Step 3b: 本地事务失败 → 回滚 half 消息                   │
│  Producer ──▶ RocketMQ: rollback ──▶ 消息删除            │
│                                                             │
│  Step 4: RocketMQ 回查(万一 Producer 挂了?)            │
│  Producer 挂了,half 消息超时未提交/回滚                  │
│  → RocketMQ 回查 Producer(问:这条消息还要吗?)         │
│  → Producer 恢复,检查本地事务状态                        │
│  → 决定 commit 或 rollback                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
java
// RocketMQ 事务消息(Java)
@Transactional
public void createOrder(OrderDTO dto) {
    // Step 1: 发送 half 消息
    TransactionMQProducer producer = new TransactionMQProducer("order-producer");
    producer.executeLocalTransaction((msg, arg) -> {
        // Step 2: 本地事务
        try {
            orderService.create(dto);          // MySQL
            stockService.decr(dto.getProductId());  // Redis
            return LocalTransactionState.COMMIT_MESSAGE;  // 提交
        } catch (Exception e) {
            return LocalTransactionState.ROLLBACK_MESSAGE;  // 回滚
        }
    }, dto);

    // Step 3: 发送业务消息(扣库存指令)
    producer.sendMessageInTransaction(msg, dto);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

第4节:Pulsar——云原生的后起之秀 ​

┌─────────────────────────────────────────────────────────────┐
│              Pulsar 分层架构(核心创新)                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │              Broker(无状态服务层)                   │  │
│  │  • 接收 Producer 消息                                │  │
│  │  • 分发消息给 Consumer                              │  │
│  │  • 无状态!可以随时重启/扩缩容!                    │  │
│  └─────────────────────────────────────────────────────┘  │
│                          │                                 │
│  ┌─────────────────────────────────────────────────────┐  │
│  │              Bookie(Apache BookKeeper,存储层)     │  │
│  │  • 消息持久化                                       │  │
│  │  • 副本机制(默认 3 副本)                         │  │
│  │  • 可以独立扩缩容                                   │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
│  对比 Kafka:                                              │
│  Kafka:每个 Broker 既处理请求,又存储数据                │
│         → Broker 挂了,它负责的分区全部不可用             │
│         → 扩容时需要迁移数据(慢!)                      │
│                                                             │
│  Pulsar:Broker 无状态,扩缩容 不需要迁移数据             │
│         → Broker 挂了,其他 Broker 立即接管               │
│         → 真正云原生                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

第5节:四强横向对比 ​

┌─────────────────────────────────────────────────────────────┐
│              消息队列四强对比                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  │ 维度        │ Kafka   │ RabbitMQ │ RocketMQ │ Pulsar  │
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 吞吐量      │ 百万级  │  十万级  │  十万级  │ 百万级  │
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 顺序消息    │ ✅分区内│  ✅队列内 │  ✅分区内│ ✅分区内│
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 事务消息    │ 仅 MQ 内部│  ❌     │  ✅跨系统│  ❌    │
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 延迟消息    │  ❌     │  ✅插件  │  ✅原生  │  ✅原生│
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 幂等性      │  ✅幂等生产者│  ✅业务层│ ✅业务层│ ✅业务层│
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 消费模式    │ pull    │  push/pull│ pull    │ push/pull│
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 部署复杂度  │  中高   │   低     │  中     │  中高  │
│  ├─────────────┼─────────┼──────────┼──────────┼─────────┤
│  │ 生态        │  成熟   │   插件多  │  阿里系   │  新兴  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

选型建议:
• 超高吞吐量(日活千万+)→ Kafka / Pulsar
• 需要事务消息(跨库原子)→ RocketMQ
• 需要灵活路由(多 Consumer)→ RabbitMQ
• 需要云原生弹性 → Pulsar
• 小型系统,不需要高吞吐 → RabbitMQ(上手最快)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

升华:MQ 选型的本质 ​

┌─────────────────────────────────────────────────────────────┐
│              MQ 选型的三个维度                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  维度 1:吞吐量(决定了你要不要选 Kafka)                 │
│  → 吞吐量 < 10 万/秒:RabbitMQ / RocketMQ 够用            │
│  → 吞吐量 > 100 万/秒:Kafka / Pulsar 必须                 │
│                                                             │
│  维度 2:功能需求(决定了你要不要选 RocketMQ)             │
│  → 需要跨数据库事务 → RocketMQ 事务消息                     │
│  → 需要延迟/定时消息 → RocketMQ / RabbitMQ 插件            │
│                                                             │
│  维度 3:运维能力(决定了你要不要选 Pulsar)               │
│  → 有 K8s + 需要弹性扩缩容 → Pulsar                       │
│  → 简单部署,不想运维太多组件 → RabbitMQ                   │
│                                                             │
│  一句话总结:                                              │
│  99% 的场景,Kafka 都不会是错误的选择。                    │
│  但如果你知道为什么选了 RabbitMQ,你的水平就更高了。        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

"AI 可查 vs 必须理解"清单 ​

AI 可查:
✅ RabbitMQ Exchange 类型的具体配置参数
✅ RocketMQ 事务消息的 Java API
✅ Pulsar Bookie 的配置项

必须理解:
🔴 四种 MQ 的核心差异(不是背表,是理解设计哲学)
🔴 RocketMQ 事务消息的 half 消息 + 回查机制
🔴 Kafka/RocketMQ 顺序消息的"分区内有序"
🔴 吞吐量 > 100 万/秒时为什么不选 RabbitMQ
1
2
3
4
5
6
7
8
9
10

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇5. RabbitMQ 深度解析 —— 灵活路由与消息可靠性 / RabbitMQ Deep Dive into Flexible Routing and Reliability
下一篇1. 搜索引擎知识体系 / Search Engine Knowledge System

持续记录,持续成长

Copyright © Tidenflow