TL;DR | 面試情境模擬 #
👴 面試官:什麼是 Message Queue?為什麼要用它?
🧑💻 你:Message Queue 是一個非同步訊息的緩衝區,讓 Producer 和 Consumer 解耦。常見用途有三個:解耦(Order Service 下單後丟訊息,Payment Service 自己去處理,互不影響)、削峰填谷(大促流量來了丟進 Queue,Consumer 按自己速度消費)、非同步處理(發信、推播等不需要等結果的操作)。Kafka 適合高吞吐的日誌/流式處理,RabbitMQ 適合需要靈活路由的任務佇列。
比喻:外賣訂單系統 #
沒有 MQ:顧客下單 → 直接等廚房做完才回應 → 廚房被癱瘓時,網站也一起掛了。
有了 MQ:
顧客下單 → 訂單丟進 Queue → 立刻回「訂單已收到」
↓
廚房系統從 Queue 取單
按自己速度處理
(就算廚房慢或短暫壞掉,訂單也不會遺失)
三大核心用途 #
1. 解耦(Decoupling) #
緊耦合(有問題):
Order Service ─── 直接呼叫 ──> Payment Service
Order Service ─── 直接呼叫 ──> Inventory Service
Order Service ─── 直接呼叫 ──> Notification Service
(任何一個掛掉,Order Service 就出問題)
解耦後:
Order Service ─── 發訊息 ──> Queue
├──> Payment Service
├──> Inventory Service
└──> Notification Service
(各服務獨立,一個掛掉不影響其他)
2. 削峰填谷(Rate Limiting / Buffering) #
流量突然暴增:
1000 req/s ──> Queue(緩衝)──> Consumer 100 req/s 穩定處理
3. 非同步處理(Async) #
發送驗證 email、更新推播、生成報表——這些不需要同步等結果的操作,丟進 Queue 後立刻回應使用者,大幅降低 API 延遲。
Kafka vs RabbitMQ #
| 特性 | Kafka | RabbitMQ |
|---|---|---|
| 設計模型 | 發佈/訂閱(Pub/Sub),Log-based | 傳統訊息佇列(AMQP) |
| 吞吐量 | 極高(百萬/秒) | 中等(數萬/秒) |
| 訊息持久化 | 預設保留(可設保留期) | 消費後即刪除 |
| Consumer | Pull(消費者主動拉) | Push(Broker 推給消費者) |
| 路由能力 | 簡單(Topic + Partition) | 靈活(Exchange + Routing Key) |
| 適合場景 | 日誌收集、事件流、資料管道 | 任務佇列、RPC、複雜路由 |
| 代表用戶 | LinkedIn、Netflix、Uber | 金融、傳統企業 |
重要概念 #
At-least-once vs Exactly-once #
- At-most-once:訊息可能遺失,不重送
- At-least-once:至少送到一次,可能重複 → Consumer 要做**冪等性(Idempotency)**處理
- Exactly-once:剛好一次(實作困難,有效能代價,Kafka 0.11+ 支援)
💡 面試官可能會追問 #
Q1:什麼是消費者偏移(Consumer Offset)? #
Kafka 的每個訊息在 Partition 裡有序號(Offset),Consumer 記錄自己讀到哪個位置。Crash 後可以從上次的 Offset 繼續讀,不會漏訊息。
Q2:如何保證訊息順序? #
Kafka 在同一個 Partition 內保證順序。如果需要按 user_id 有序,把同一個 user 的訊息路由到同一個 Partition(用 user_id 作為 Partition Key)即可。
Q3:Queue 滿了怎麼辦? #
- Kafka:根據保留策略刪除舊訊息(time-based 或 size-based)
- RabbitMQ:可以設定
x-max-length,超過後丟棄舊訊息或拒絕新訊息 - 根本解法:Consumer 速度跟上,或增加 Consumer 數量