iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Software Development

30 天把舊 ERP 整合成現代微服務平台:架構治理與工程實作雙軌實戰系列 第 18 篇

Day 18|Kafka 與 RabbitMQ:不是競爭,而是不同任務

  • 分享至 

  • xImage
  •  

Kafka 與 RabbitMQ 都能傳訊息。處理完還要保留嗎?新的下游加入時,需要重播嗎?這些問題會比先比較效能數字更接近實際需求,所以要選哪一個,我會先想訊息之後要怎麼用。

本篇名詞小筆記

  • Kafka:分散式事件串流平台,適合需要保留、重播並讓多個下游各自消費的事件。
  • RabbitMQ:訊息 broker,擅長工作佇列、確認機制與彈性的訊息路由。
  • Partition:Kafka 分割區;同一分割區內的事件保有順序,也是平行消費與擴充的基本單位。
  • DLQ:死信佇列(Dead Letter Queue),用來存放無法順利傳遞或處理的訊息,等待人工接手。
  • DLX:死信交換器(Dead Letter Exchange),RabbitMQ 用來把無法處理的訊息轉送到死信佇列的路由設定。

今天要解決的問題

有些訊息要讓好幾個下游各自使用,之後還可能重新處理;有些則是一件待完成的工作。先把保留、消費與重播的需要寫下來,再比較平台的模型,就比較容易知道自己在選什麼。

能力 Kafka RabbitMQ
核心模型 Append-only log Exchange、queue、binding
重播 原生依 offset 通常需另行設計
常見用途 主資料事件、串流整合 指令、工作派送、複雜路由
順序 Partition 內 Queue/consumer 設計
失敗處理 offset、retry topic nack、redelivery、DLX

架構師視角:先確認保留與重播需求

放在這個系列裡,物料變更可以評估 Kafka,讓下游建立資料投影;EDI 的工作派送可以評估 RabbitMQ。不過,這只是候選分工,是否真的需要兩套,我還是會把需求與維護成本一起算過。兩邊都不符合的話,我會回頭想這件事是不是根本不需要非同步。

https://ithelp.ithome.com.tw/upload/images/20260925/20184230MTfq4igYa6.png

圖 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 故障後重啟 是否從正確位置繼續?是否重複處理?
重複投遞 冪等處理是否生效?
訊息堆積 是否觸發告警?回復後能否追上?

同一筆事件再來,資料會不會多寫、通知會不會多發,光看程式碼看不出來,所以重複投遞我會刻意測一次,實際確認業務流程有沒有準備好。

今天先整理到這裡

選好訊息平台,只是完成了一部分。接下來,我更想確認事件送到之後,業務能不能正確處理。下一篇,就從重複事件與冪等開始。

參考資料

  1. Apache Kafka, Apache Kafka Documentation,查閱日期:2026-10-01。
  2. RabbitMQ, RabbitMQ Consumer Acknowledgements,查閱日期:2026-10-01。
  3. RabbitMQ, RabbitMQ Consumer Prefetch,查閱日期:2026-10-01。

上一篇
Day 17|REST 還是 MQ?先問業務是否需要立即答案
系列文
30 天把舊 ERP 整合成現代微服務平台:架構治理與工程實作雙軌實戰 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言