選 message broker 的時候 google 一搜會找到 50 篇「RabbitMQ vs Kafka」——但他們大多寫成 feature 對比表,看完還是不知道自己場景該選哪個。

這篇不重複那些表格。直接給你對應場景的 cheat sheet——你的 use case 落在哪一格、選哪個、為什麼。讀完 10 分鐘做出判斷。

讀這篇前建議先看 #04 演進史#06 演進驅動力——這篇是前面兩篇的決策版本。


一張 cheat sheet 直接給場景對應

你的場景推薦為什麼
一般 web app 的 background job(email / 報表 / image processing)RabbitMQgeneral-purpose 最成熟、客戶端最廣
Throughput < 10K msg/s 的事件總線RabbitMQKafka overkill、運維重
Throughput > 50K msg/s 的 streaming(log / metrics / activity)Kafkalog-based 架構天生擅長
需要重新消費歷史訊息(offset replay)Kafka唯一原生支援的
多 consumer group fan-out(同一事件多 service 消費)Kafkaconsumer group 模型天生支援
Routing 邏輯複雜(broker 層 conditional routing)RabbitMQTopic / Direct / Header Exchange 強大
已經有 Redis、想要簡單 streamRedis Streams零新增運維
Microservice mesh、cloud-native 環境NATS輕量、單 binary、subject-based
低延遲(p99 < 5ms)需求NATS / RabbitMQKafka 達不到
跟大數據生態整合(Spark / Flink)Kafka原生最佳
嚴格 ordering(按 producer 順序)Kafka 單 partition / RabbitMQ 單 queue都行,但 partition 限制 throughput
簡單 task queue(BullMQ / Celery / Sidekiq 後面那層 broker)Redis Streams這些 framework 預設或良好支援

90% 的選型 case 在這張表裡能找到對應。剩下 10% 是混合需求(例如「我要高 throughput 但又要複雜 routing」),那是 case-by-case 的工程取捨——通常用兩種 broker 並存解。


各自的強項清單(單頁版)

RabbitMQ — General-purpose 之王

強項

  • AMQP 開放標準,跨語言 client 最齊全
  • Routing 機制完整(Topic / Direct / Fanout / Header Exchange)
  • DLQ / TTL / priority queue 等可靠性 feature 內建
  • 學習曲線平緩,mental model 直觀
  • 中等規模(< 50K msg/s)下無敵手
  • 運維工具成熟(RabbitMQ Management UI 開箱即用)

弱項

  • Throughput 上限約 50K msg/s(單 broker,HA cluster 也撐不到 Kafka 級別)
  • 不能 replay 歷史訊息(消費完即刪)
  • Fan-out 加 consumer 要建新 queue
  • HA cluster 配置 + failover 比 Kafka 弱

典型 use case:Web app background job、email queue、notification、訂單處理 pipeline

Kafka — 大數據 streaming 之王

強項

  • Throughput 100K-1M msg/s 級別(單 cluster 可達 10M+)
  • Log-based 模型支援 offset replay
  • Consumer group 模型對 fan-out 友善
  • 大數據生態原生整合(Spark / Flink / Connect / KSQL)
  • Schema Registry 支援強型別演化

弱項

  • 運維重(partition / replica / ZooKeeper 或 KRaft / JVM tuning)
  • 學習曲線陡(Consumer rebalance / partition reassignment 都是坑)
  • Latency 比 RabbitMQ 差(為 throughput 優化)
  • 小規模場景 overkill
  • Routing 簡單,broker 層只能 partition by key

典型 use case:Activity / log / metrics streaming、事件 bus(多 consumer group)、CDC pipeline、即時分析

NATS / NATS JetStream — Cloud-native 輕量代表

強項

  • 超低延遲(p99 < 1ms)
  • 單一 binary 部署,零依賴
  • Subject-based routing 比 Kafka topic 彈性
  • 原生 cloud-native(K8s / mesh 整合好)
  • JetStream 補上 Kafka-like persistence 但保持輕量

弱項

  • 生態相對小(vs Kafka 龐大生態)
  • Throughput 比 Kafka 略低(單 broker 約 100K msg/s,cluster 擴展性沒 Kafka 強)
  • 主流團隊保守選型仍偏 Kafka,hiring 找懂 NATS 的人較難

典型 use case:Microservice mesh、低延遲事件 bus、IoT、cloud-native 新建專案

Redis Streams — 已有 Redis 的最簡選擇

強項

  • 零新增運維(Redis 你已經有)
  • 延遲低(in-memory)
  • API 簡單(XADD / XREAD / XACK)
  • 跟 Redis 其他資料結構(Pub/Sub / Hash / List)共存

弱項

  • Persistence 弱於 Kafka / RabbitMQ(AOF 即使開到 every-write 也不如 disk-first MQ)
  • Throughput 比 Kafka 低一個級距(單 instance 約 50-100K msg/s)
  • Memory 限制(資料量大時要 sharding)
  • Cluster 模式下 Streams 有些限制

典型 use case:BullMQ / 簡易 task queue、輕量事件 stream、已用 Redis 的小型專案


Migration 難度估算

換 broker 不是 free——大致估算讓你預估成本:

從 → 到難度主要痛點
RabbitMQ → Kafka⭐⭐⭐⭐mental model 差異大、Consumer Group / offset 全新概念、運維鏈路重做
Kafka → RabbitMQ⭐⭐⭐mental model 差異大但相對簡單、ack 機制要重學
RabbitMQ → Redis Streams⭐⭐API 不同但概念接近、適合 task queue 場景
Kafka → NATS JetStream⭐⭐⭐concept 接近但 client lib / tooling 重做
任意 → managed(Confluent / MSK / CloudAMQP)主要是運維搬遷,code 不太動

重點:migration 成本通常 1-3 個月(看團隊規模 + 訊息量)。所以第一次選對最重要


常見的選型 anti-pattern

1. 「我們公司都用 Kafka」cargo cult

別人用 Kafka 是因為他們撞到 Kafka 才解的極限。你沒撞到極限就用 Kafka = 用大砲打蚊子。先看你實際 throughput / latency / replay 需求再決定。

2. 「未來會大規模所以先用 Kafka」

YAGNI。現在 1K msg/s 上 Kafka,等實際撞到 50K msg/s 再考慮,到那時候你的問題已經不是「broker 選型」了。先用 RabbitMQ,撞牆再換——換的成本比現在 over-engineer 的成本低。

3. 「Kafka 的功能比較多」

功能多 ≠ 你需要。你的場景需要 offset replay 嗎?需要 5 個 consumer group 嗎?需要 Schema Registry 嗎?沒用到的功能是運維負擔,不是 leverage。

4. 「我們有 SRE 不怕運維」

運維成本不只是 SRE 時間。是 dev team 的 cognitive overhead、incident response 的回應速度、新人 onboarding 的曲線。全部加總比 SRE 工時貴

5. 「Open source 最好」

NATS / Redis Streams / Kafka / RabbitMQ 都 open source。但 self-host vs managed(Confluent / MSK / CloudAMQP)的決策更重要——大多數團隊用 managed 讓 broker 變黑盒比自己跑 cluster 划算。


我自己跑了一輪(local docker bench)

寫這篇前我自己在 local docker 跑了一輪——4 個 broker + 1 個 FastAPI backend AP,用 HTTP load test 打 1000 events / broker,量端到端 latency。

setup

  • Docker Desktop(Win 11 / WSL2)
  • 4 個 broker:RabbitMQ 3.13、Apache Kafka 3.8(KRaft mode)、NATS 2.10 + JetStream、Redis 7
  • 1 個 FastAPI backend,4 個 endpoint 各對應一個 broker
  • Producer:HTTP POST,每筆事件含 4 個下游 handler(email / inventory / analytics / recommender),handler 模擬 1-5ms 處理
  • 1000 events / broker,sequential(單 client)

結果

BrokerRPSHTTP p50 (ms)HTTP p95HTTP p99Backend publish p50E2E consumer p50E2E consumer p99
RabbitMQ96.79.5815.7720.282.9310.5626.42
Kafka84.710.7617.8623.874.1513.4029.99
NATS119.17.9012.0016.721.668.9315.32
Redis Streams115.77.7114.3420.641.2022.0045.26

幾個觀察

1. NATS 在這個 setup 下贏在所有面向——HTTP p50 最低(7.9ms)、publish 最快(1.66ms)、consumer e2e 也最低(8.93ms)。這對應到 NATS「為低延遲設計」的定位。

2. Kafka 的 latency 是 4 個裡面最高的——HTTP p50 10.76ms,比 NATS 多 36%。這完全符合 Kafka「為 throughput 優化」的設計取捨。Local docker single-broker 的 Kafka 不是它真實 production 性能——production 多 broker / 多 partition 時 Kafka 才能展現它的 throughput 優勢。

3. Redis Streams 的 publish 最快(1.2ms)但 consumer e2e p99 反而最高(45ms)——原因是 Redis Streams pull-based + 我這邊 batch 設成 10、block timeout 5 秒,consumer 不是 instant 拉取。改 batch=100 / block=100ms 應該能讓 e2e latency 下來。這是一個 Redis Streams 實作細節:publish 飛快但 consumer 端要自己調 polling 行為

4. RabbitMQ 在 single-broker 場景表現平均——沒有任何 dimension 最強但也沒最弱。這對應到它「general-purpose」的定位:沒有特別擅長的 case,但每個 case 都跑得穩

注意:這不是 production benchmark

  • Local docker single-machine,CPU / IO / network 都比 production 弱
  • Single producer / single consumer,沒測 horizontal scale
  • 1000 events 樣本太小,不夠看 throughput 上限
  • 沒測 message 大小變化(payload 都是 ~150 bytes)

但對於「這 4 個 broker 在 single-machine 場景的相對 latency」,這個數據夠看出 pattern。完整 setup + script 在 tmp/mq-bench-2026-04-30/(短期 scratch,做完會清掉)。

Sample 後端 log(一筆 RabbitMQ 事件被 4 個 handler 平行處理):

[backend] INFO  POST /events/rabbitmq → event_id=18c09b64...
[backend] INFO  [rabbitmq] analytics      event_id=18c09b64...
[backend] INFO  [rabbitmq] inv_handler    event_id=18c09b64...
[backend] INFO  [rabbitmq] recommender    event_id=18c09b64...
[backend] INFO  [rabbitmq] email_handler  event_id=18c09b64...

注意 4 個 handler 的執行順序不是「email → inv → analytics → recommender」固定順序——是 asyncio.gather() 並行跑、順序依各 handler 完成時間決定。這是 event-driven 架構的本質:handler 之間不該有 ordering dependency,否則就該寫成同步 chain(MVC 風格),詳見 #18 MVC vs Event-driven


我自己的偏好(個人立場)

如果你問我從零開始選——

新建專案、規模未知RabbitMQ。理由:成熟、客戶端齊、mental model 簡單、有 SRE 之前自己也撐得住、撞牆再換成本可控。

新建專案、確定大規模 streamingKafka(managed)。理由:撞 RabbitMQ 牆基本確定,直接用 Confluent / MSK 跳過運維重的痛。

新建專案、cloud-native + 低延遲NATS JetStream。理由:輕量、運維小、未來換 Kafka 的概念還算接近。

已用 Redis、需要輕量 streamRedis Streams。理由:零新增運維。

我不會主動推 Kafka 給小規模團隊,也不會推 RabbitMQ 給已經在做大數據 streaming 的團隊。該推的推、不該推的不推——這是 broker 選型最重要的紀律。


反思

選 broker 的核心問題不是「哪個 broker 最好」,是「我的場景需要什麼,最便宜的 broker 是哪個」。

便宜不只是錢——是運維時間、團隊認知負擔、incident response 速度全部加總。

如果你正在選或正在評估換 broker,問自己這三個問題:

  1. 我的 throughput 真的需要 Kafka 嗎?實際 metrics 是多少?
  2. 我換 broker 的 driver 是「撞了具體極限」還是「跟風 / 規格更全 / 未來會用到」?
  3. 換完之後 6 個月,team 有 incident 時的 MTTR 會變好還是變差?

三個問題誠實答完,broker 選型 90% 的時候有清楚答案。