問題背景
我們的 Kafka Topic 設計是依照平台分類:
- action-to-shopee
- action-to-momo
- action-to-yahoo
雖然做到了一定程度的收斂,但隨著業務複雜度增加,問題浮現了。
問題現象
客戶抱怨:「為什麼列印小白單要等這麼久?」
實際情況
- 列印小白單只需要 5 秒
- 但前面卡了一個「查詢訂單」的 Queue 需要 3 分鐘
- 客戶感受到的是 3 分 5 秒
更慘的是遇到回滾或大促,訂單 API 可能要打 10 分鐘以上。
問題分析
不同類型的工作,處理時間差異巨大:
| 工作類型 | 處理時間 | 即時性需求 |
|---|---|---|
| 列印小白單 | 5 秒 | 高(用戶等待) |
| 上下架商品 | 10-30 秒 | 中 |
| 查詢訂單 | 1-3 分鐘 | 低 |
| 回滾訂單 | 10+ 分鐘 | 低 |
把它們放在同一個 Topic,快的被慢的拖累。
解決方案比較
| 方案 | 做法 | 優點 | 缺點 |
|---|---|---|---|
| 增加 Topic | 分 urgent/normal/low 三個 Topic | 簡單明確 | 每個 Topic 都佔用 Partition 和 IO |
| 增加 Consumer Group | 同 Topic 不同 Group 處理 | 不增加 IO | 大部分訊息被丟棄,浪費 Offset |
| 指定 Partition + Offset | 程式層面控制 | 完全不影響 IO | 程式複雜度高 |
我們的選擇:Topic 分流
新的 Topic 設計
// 高優先:用戶等待的操作
action-to-shopee-urgent
// 正常:一般業務操作
action-to-shopee-normal
// 低優先:背景任務
action-to-shopee-low
訊息路由邏輯
public void sendAction(Action action) {
String topic = switch(action.getPriority()) {
case URGENT -> "action-" + platform + "-urgent";
case NORMAL -> "action-" + platform + "-normal";
case LOW -> "action-" + platform + "-low";
};
kafkaTemplate.send(topic, action);
}
優先級定義指南
URGENT(緊急)
- 用戶正在等待結果
- 處理時間 < 30 秒
- 例:列印、查詢庫存
NORMAL(正常)
- 一般業務操作
- 處理時間 30 秒 ~ 3 分鐘
- 例:上下架、更新價格
LOW(低優先)
- 背景任務
- 處理時間可能很長
- 例:回滾、批次同步
關鍵學習
每一個 Queue 的定義和範圍大小不同,要區分是情境的重還是需求的重,並正確地拆分。
設計原則
- 按處理時間分流:快的不要被慢的擋住
- 按即時性分流:用戶等待的優先處理
- 預留擴展空間:未來可能需要更細的分類
發佈留言