Kafka 與 RabbitMQ 都能傳訊息。處理完還要保留嗎?新的下游加入時,需要重播嗎?這些問題會比先比較效能數字更接近實際需求,所以要選哪一個,我會先想訊息之後要怎麼用。
有些訊息要讓好幾個下游各自使用,之後還可能重新處理;有些則是一件待完成的工作。先把保留、消費與重播的需要寫下來,再比較平台的模型,就比較容易知道自己在選什麼。
| 能力 | Kafka | RabbitMQ |
|---|---|---|
| 核心模型 | Append-only log | Exchange、queue、binding |
| 重播 | 原生依 offset | 通常需另行設計 |
| 常見用途 | 主資料事件、串流整合 | 指令、工作派送、複雜路由 |
| 順序 | Partition 內 | Queue/consumer 設計 |
| 失敗處理 | offset、retry topic | nack、redelivery、DLX |
放在這個系列裡,物料變更可以評估 Kafka,讓下游建立資料投影;EDI 的工作派送可以評估 RabbitMQ。不過,這只是候選分工,是否真的需要兩套,我還是會把需求與維護成本一起算過。兩邊都不符合的話,我會回頭想這件事是不是根本不需要非同步。

圖 Day 18-1:Kafka 與 RabbitMQ 邊界。
保留與重播如果一開始沒準備,之後要補歷史資料,就可能需要再從資料庫重建,所以我會先問這件事。提早想好,能少一些後續另外維護的轉換流程。
Kafka 的順序保證在 partition 內,所以同一筆訂單的事件要怎麼分配,會和 partition key 有關,順序也值得先確認。我會在這裡多花一些時間,確認流程真正需要的順序。
兩套平台差別再大,有幾件事都跑不掉:訊息格式(schema)要先講好、同一筆訊息重複進來結果要一樣(冪等)、失敗要能重送,容量與監控也要一起安排。剩下的才是各自的動作:Kafka 多看 partition、consumer group 與 lag;RabbitMQ 多看 ack、prefetch、unacked message 與 dead-letter exchange。
Kafka 這一側最直接的指標是 lag,也就是已經寫進去、但還沒被讀走的訊息數。lag 持續變大,代表處理的速度跟不上進來的速度。這時候第一個念頭通常是多開幾個 Consumer,但在傳統的 consumer group 裡,一個 partition 只會分給一個 Consumer,partition 只有三個,第四個 Consumer 就只能閒著。所以我會先看單筆處理花多久、瓶頸是不是其實在下游的資料庫,再決定要不要調整 partition 數量。
RabbitMQ 這一側要看的是 prefetch 與 ack。prefetch 決定一個 Consumer 一次可以先拿走幾則訊息,設得太大,訊息會集中在先拿到的那幾台手上:佇列本來就有積壓時,先連上來的 Consumer 會一口氣把整批拿走,後面才上線的只能等新訊息;已經拿走的也不會退回重派,所以那一台慢下來,這批訊息就跟著慢,其他台就算是閒的也接不了手。ack 則是處理完的回報;拿走了卻還沒 ack 的訊息叫 unacked,broker 會一直幫它留著,也不會改派給別人。這種卡住從佇列長度看不出來,訊息已經不在排隊,而是在某台 Consumer 手上,所以 unacked 要單獨列入監控,才知道是還在處理、卡在外部系統,還是程式忘了回報。
死信佇列(Dead Letter Queue)裡躺的每一則,都是一筆還沒完成的業務工作——例如一張 EDI 訂單沒進系統,但客戶那邊以為已經送出去了。沒有客訴、也沒有錯誤畫面,除非有人主動去看,否則它會一直留在佇列裡。所以我把這件事寫成告警:relay 的死信佇列只要連續五分鐘有訊息,就通知負責 EDI 的人,告警上直接掛 runbook 與 Dashboard 連結,接手的人不用先找文件。
| 取捨 | 這樣選的理由 | 何時要重新評估 |
|---|---|---|
| 主資料事件用可保留、可重播的模型 | 新增下游時能回填歷史 | 保留成本超過重播帶來的價值時 |
| 工作派送用佇列模型 | 訊息處理完即結束,不需保留 | 開始出現重播或多訂閱需求時 |
| 先以單一平台滿足需求 | 兩套平台的技能、升級與值班成本加倍 | 單一平台明顯無法滿足某類需求時 |
| DLQ 訊息設負責人與期限 | 失敗訊息代表未完成的業務事件 | 無 |
多一套平台,要有人懂它、要跟著它升級、半夜出事要有人處理。所以只要一套還夠用,我會先把這套用熟,真的不夠用再考慮第二套。
測試應涵蓋 producer、broker、consumer 任一端故障或重啟,以及重複投遞與訊息堆積:
| 測試情境 | 想確認什麼 |
|---|---|
| producer 故障後重啟 | 未確認送出的訊息是否遺失或重複? |
| broker 重啟 | 訊息是否持久化?consumer 是否自動恢復? |
| consumer 故障後重啟 | 是否從正確位置繼續?是否重複處理? |
| 重複投遞 | 冪等處理是否生效? |
| 訊息堆積 | 是否觸發告警?回復後能否追上? |
同一筆事件再來,資料會不會多寫、通知會不會多發,光看程式碼看不出來,所以重複投遞我會刻意測一次,實際確認業務流程有沒有準備好。
選好訊息平台,只是完成了一部分。接下來,我更想確認事件送到之後,業務能不能正確處理。下一篇,就從重複事件與冪等開始。