題幹與適用場景
支付、工單與資源建立 API 可能遇到請求已執行但回應遺失。客戶希望用 Idempotency-Key 安全重試。請決定是否推出,並說明承諾邊界、優先客戶、指標、成本與失敗回滾。
面試官考察點
考察你能否把協定能力轉成可驗證產品契約:支援哪些操作、鍵的生命週期、參數不一致如何處理、重複請求如何回應,以及如何平衡可靠性、儲存成本與開發者體驗。
回答前需要釐清的問題
先確認客戶最痛的副作用是重複扣款、重複資源還是重複通知;再問請求量、重試窗口、跨區域需求與合規留存。也要區分「伺服器去重」與業務交易真正成功,避免把網路重試承諾擴大成 exactly-once。
30 秒回答
「我會先針對高風險寫入提供有邊界的冪等鍵,而不是承諾所有介面 exactly-once。契約應規定鍵格式、租戶範圍、保存窗口、參數指紋與重複回應;同一鍵不同參數必須報錯。先用支付與資源建立客戶試點,追蹤重複副作用率、安全重試成功率、儲存成本與支援工單,再用灰度和清楚的 409/422 語意擴大範圍。」
分步驟深入解答
定義使用者價值
把「逾時後敢重試」作為核心結果,優先有財務或資源副作用的 POST。唯讀請求和天然冪等的 PUT 不應為了行銷而重建。
寫清契約邊界
規定鍵在租戶內唯一、長度上限、保存窗口與可重試狀態。伺服器保存首次請求的狀態碼與回應本文;同鍵不同參數回傳衝突,避免靜默重用錯誤結果。
連接業務交易
去重記錄必須與副作用提交處在同一可靠交易,或具備可恢復 outbox。快取命中不能證明下游支付已結算;非同步工作要回傳可查詢的 operation id。
設計錯誤與相容
區分處理中、已成功、已失敗與已過期。客戶端 SDK、文件與閘道要一致傳遞鍵;舊客戶端仍可運作,但不能獲得重複保護的隱含承諾。
選擇指標與成本
核心指標是重複副作用率與安全重試成功率,護欄包括鍵儲存容量、P95 延遲、衝突率與支援量。按租戶和風險等級估算 TTL 與儲存,不要無限保存回應。
分階段發布
先在單一區域、支付沙箱與內部 SDK 開啟,以影子去重日誌驗證命中率,再讓少數租戶 opt-in。出現回應不一致、儲存失控或下游不支援交易時,關閉新入口但保留舊請求路徑。
高品質示範回答
我會把冪等鍵定位為高風險寫入的重試安全契約。先選支付與資源建立,規定租戶範圍、鍵格式、保存窗口、參數指紋與重複回應;同鍵不同參數報衝突,非同步副作用回傳可查詢 operation id。指標同時看重複副作用率、安全重試成功率、P95 延遲、衝突率與儲存成本,先沙箱與 opt-in 灰度,交易或下游能力不足時不擴大承諾。
常見錯誤
承諾 exactly-once
冪等鍵主要消除客戶端重複提交,不能涵蓋下游不可恢復副作用;應明確 at-most-once 處理與最終狀態查詢。
無限保存鍵
永久保存帶來成本、隱私與清理問題;按風險定義 TTL,並記錄清理後的過期語意。
忽略參數變化
同鍵不同請求若回傳第一次結果,會隱藏客戶端錯誤;應保存參數指紋並回傳衝突。
只做閘道快取
閘道快取與業務交易可能分離;關鍵去重記錄要與副作用有可靠一致性或可恢復補償。
追問及應對
為什麼不讓所有 POST 都支援?
不同寫入的副作用和成本不同;先覆蓋高風險場景,避免對低價值介面製造複雜契約。
重試時第一次請求仍在處理怎麼辦?
回傳明確的處理中狀態與 operation id,讓客戶端輪詢或訂閱,不並行執行第二個副作用。
多區域如何保證鍵一致?
先限定單主區域或按租戶分片;跨區域需要一致的去重儲存與故障演練,不能只複製快取。
失敗回應能否重用?
契約應區分可重試的暫時失敗與已確定失敗,並說明是否快取狀態碼和回應本文;Stripe 的實務會保存首次結果,因此要讓客戶理解 TTL 與錯誤語意。