大綱

  • 為何 idempotency 是分散式系統一級屬性:retry / failover / replay 的前提
  • idempotency key 的設計:來源、生命週期、儲存
  • exactly-once 是幻象、at-least-once + idempotent 才實際
  • replay 驗證:從 log / event store 重播能否得到相同最終狀態
  • 03 message-queue 的關係:consumer idempotency 是延伸專題
  • payment / order / messaging 的 idempotency 模式差異
  • 6.4 chaos 的整合:注入重複訊息驗證冪等
  • 反模式:idempotency 只靠 DB unique constraint、無 key 設計;retry 後副作用重複;replay 路徑從未驗證

概念定位

Idempotency 與 replay 驗證是把重試、重播與副作用控制變成可驗證屬性,責任是讓 at-least-once 與 failover 不會把系統推向重複執行。

這一頁處理的是分散式系統的重複輸入問題。只要有 retry、補償或訊息重送,冪等性就是正確性前提,把它當優化項會低估風險。

核心判讀

判讀 idempotency 時,先看 key 的生命週期,再看 replay 是否能落在同一狀態。

重點訊號包括:

  • idempotency key 是否由 server 可控、可追蹤
  • replay 路徑是否與 production 對齊
  • late retry 是否會被誤視為新請求
  • 重複副作用是否能靠狀態機吸收

案例對照

  • Stripe:交易流程需要嚴格控制重複請求。
  • GitHub:webhook / event replay 經常直接暴露冪等缺口。
  • Slack:訊息與通知類流程特別依賴重複輸入控制。

支付類 Idempotency 的設計約束

支付類 idempotency 的核心約束是「key 邊界跟業務操作邊界一致」 — 同一筆支付的所有 retry 必須共用 key、跨支付 key 必須不同、key 不可被偽造、且要保留足夠重放證據。失敗代價(重複扣款、重複建單)讓這四個約束從 best practice 變成正確性前提。

對應 S1 Stripe Idempotency 與零停機遷移 揭露的 idempotency key 跟 transaction-path observability 兩個機制(S1 case 直接列出);以下實作層判讀條件屬通用工程知識展開、case 本身只給「key 跟業務邊界一致」這一條方向。

實作層的判讀條件:

  • Key 邊界跟業務一致:同一筆支付的 retry 共用 idempotency key、跨支付 key 不同。Key 來源 / TTL / fallback 設計屬實作細節、跟 6.12 SSoT 描述的 server 端 key 設計呼應
  • 保留足夠證據供重放:transaction-path observability 要覆蓋交易關鍵欄位、讓 reconciliation 跟稽核可重放判讀

6.11 migration-safety 交易類段 共用 transaction-path observability、避免 migration 期間 idempotency 判讀失效。支付 reconciliation 跟交易語義詳見 01 資料庫模組(具體章節依 reconciliation / transaction 主題、目前待 01 模組對應頁建立)。

下一步路由

  • 03 message-queue:consumer 端冪等設計
  • 06.4 chaos:注入重複訊息驗證
  • 06.7 DR:replay 作為回復手段的前提

判讀訊號

  • 用戶被重複扣款 / 重複建立資源、靠人工對帳發現
  • retry policy 開啟後事故變嚴重、不敢開 retry
  • replay 從 event store 跑一次、結果跟 production 不同
  • idempotency key 從 client 端帶上來、無 server 端 fallback
  • key TTL 過短、晚到的 retry 變成新請求

交接路由

  • 03 message-queue:consumer idempotency 實作
  • 06.4 chaos:注入重複訊息 / 故障 retry 場景
  • 06.7 DR:replay 作為回復手段的前提
  • 07 資安:idempotency key 不可被預測 / 偽造