Kafka 實務坑筆記(三):Partition Key 設定不當導致重複處理

問題現象

用戶下訂單後要出貨,但系統竟然發動了兩次一模一樣的取號 Job,導致:

  • 一個取號成功
  • 一個取號失敗
  • 用戶體驗極差

問題分析

背景條件

  • 巡邏檢查每 3 秒打一次 Queue
  • 正式環境有兩台 Job 機
  • Queue 與 Queue 之間沒有其他 Queue 插入

發生了什麼?

當沒有指定 Partition Key 時,Kafka 會自動將訊息分散到不同的 Partition。這導致:

  1. 同一張訂單的 Queue 被分到不同 Partition
  2. 兩台機器同時消化到相同訂單的 Queue
  3. 兩台同時去取號 → 碰撞發生

解決方案比較

方案 做法 優點 缺點
快取 + Lock 處理前檢查鎖 不改架構 極限情況仍可能碰撞,且拖慢速度
指定 Partition Key 用訂單 ID 當 Key 確保順序 可能造成熱點 Partition

Partition Key 設計原則

不設定 Key(null)

  • Kafka 自動分散到各 Partition
  • Consumer 程式必須是無狀態的
  • 適合:獨立任務、無順序要求

設定 Key

  • 相同 Key 的訊息會進入同一個 Partition
  • 確保順序性
  • Consumer 必須處理有序邏輯
  • 適合:有狀態的任務、需要順序保證

最佳實踐

選擇合適的 Partition Key

// 好的選擇:訂單 ID(確保同一訂單順序處理)
producer.send(new ProducerRecord(topic, orderId, message));

// 避免:用戶 ID(可能造成熱點)
// 大戶用戶的訂單會集中在同一個 Partition

考慮因素

  1. 業務邏輯:是否需要順序保證?
  2. 分布均勻度:Key 的基數是否足夠大?
  3. 熱點風險:是否有超大 Key 導致傾斜?

Partition Key 的設計直接影響系統的正確性性能,務必謹慎選擇。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *