Idempotency(冪等性)
my-notes/system-design-hld/concepts · ZH
translationKey: idempotency
#system design
#concept
🧱 Idempotency(冪等性)
🧩 一、定義
Idempotency(冪等性) 指的是: 不管同一個請求執行幾次,結果都一樣、不會造成副作用重複發生。
以數學語言表示:
f(f(x)) = f(x)
也就是「多次執行,結果不會改變」。
💡 二、白話例子
| 狀況 | 是否冪等 | 說明 |
|---|---|---|
查詢用戶資料 GET /user/123 |
✅ 是 | 查幾次都一樣,不影響狀態 |
刪除帳號 DELETE /user/123 |
✅ 是 | 刪一次與刪十次結果都一樣 |
新增訂單 POST /order |
❌ 否 | 多送幾次會多建立幾筆訂單 |
更新用戶資料 PUT /user/123 |
✅ 是 | 多次更新同樣內容不影響結果 |
增加餘額 POST /deposit |
❌ 否 | 每次都會加錢(重複執行有副作用) |
⚙️ 三、為什麼要在 Webhook / API 中確保冪等性?
因為:
- 網路不穩、超時、重試常見(例如第三方服務會重送事件)
- 如果沒有冪等控制,可能導致「同一事件重複執行多次」
- 重複付款
- 重複寄信
- 重複入庫
Webhook 與金融交易特別需要冪等性保證。
🧠 四、常見實作策略
✅ 1️⃣ 使用 Idempotency Key(冪等鍵)
客戶端在每次請求時附帶一個唯一識別碼:
POST /payment
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
伺服器端邏輯:
def create_payment(request):
key = request.headers.get("Idempotency-Key")
if key in cache:
return cache[key] # 回傳之前的結果
result = process_payment()
cache[key] = result
return result
✅ 2️⃣ 使用「唯一事件 ID」
Webhook 通常自帶事件編號:
{
"id": "evt_123456789",
"type": "payment_succeeded"
}
你可以:
- 將事件 ID 存進資料庫(或 Redis)
- 若再收到相同 ID → 忽略處理
✅ 3️⃣ 使用交易 / 鎖機制(Database Transaction)
INSERT INTO payments (id, amount) VALUES ('evt_123', 100)
ON CONFLICT (id) DO NOTHING;
即使重複執行,也只會插入一次。
✅ 4️⃣ 在應用層設計「去重策略」
- 記錄最近已處理的事件 Hash / UUID
- 可結合 TTL(例如只保存近 24 小時的事件)
- 通常放在 Redis,查詢 O(1)
🔐 五、冪等與非冪等的 API 方法對照
| HTTP 方法 | 預期是否冪等 | 範例 |
|---|---|---|
| GET | ✅ 是 | 查詢資料 |
| PUT | ✅ 是 | 更新整個資源 |
| DELETE | ✅ 是 | 刪除資源 |
| POST | ❌ 否 | 新增資源(可透過 Idempotency Key 變冪等) |
| PATCH | ⚠️ 視情況而定 | 更新部分欄位,取決於實作 |
💡 六、實務場景舉例
📦 Stripe Webhook
- 每個事件有唯一
event.id - Stripe 可能重送多次事件
- 官方建議:「伺服器要能根據
event.id判斷是否已處理過」
🏦 銀行轉帳 API
- 每次轉帳請求都帶一個
transaction_id - 後端只處理一次,重複傳相同 ID 會直接回「已完成」
🧱 七、與「重試機制」的關係
重試是為了「確保成功」 冪等是為了「確保不重複執行」
有重試 → 必須有冪等
否則在 timeout 重送時,就可能造成:
- 重複下單
- 重複扣款
- 重複通知
🚀 八、設計建議懶人包
| 主題 | 建議 |
|---|---|
| 💡 核心觀念 | 同一請求多次執行結果一致 |
| 🔑 實作方式 | Idempotency Key / Event ID / DB unique constraint |
| 🧱 儲存位置 | Redis、DB、Message queue metadata |
| 🧩 典型應用 | 支付、Webhook、訂單建立、Email 寄送 |
| ⚠️ 注意 | 伺服器端必須驗證與記錄,不可只靠前端 |
| 🚀 目標 | 「重送沒事、只送一次生效」 |
✅ 總結一句話
Idempotency(冪等性)= 重送沒副作用的保險機制。
在設計任何可能被重試、被重送的系統(例如 Webhook、交易 API)時, 冪等性是讓你「放心重送、不怕重複」的關鍵保護機制。
尚無其他語言版本