故障處理模式 (Fault Handling Patterns)
核心前提
永遠假設網路呼叫會失敗、被延遲或回傳意外結果。
分散式系統最危險的假設是「網路是可靠的」。
三個必備模式:
| 模式 | 解決問題 | 關鍵字 |
|---|---|---|
| 重試 + 退避 + 抖動 | 暫時故障 | exponential backoff + jitter |
| 冪等性 | 重試的副作用 | idempotency key |
| 熔斷器 | 級聯故障 | Closed → Open → Half-Open |
逾時、重試與退避
逾時(Timeout):超過預期時間就放棄,不要無限等待。
重試(Retry):適合暫時故障,但需要配合退避策略:
立即重試(錯誤做法):
t=0 ──► 失敗
t=0 ──► 重試,失敗
t=0 ──► 重試,失敗
(所有客戶端同步打爆伺服器)
指數退避 + 抖動(正確做法):
t=0 ──► 失敗
t=1s + random(0~0.5s) ──► 重試
t=2s + random(0~1s) ──► 重試
t=4s + random(0~2s) ──► 重試
(延遲分散,伺服器有時間恢復)
面試魔法短語
「retry with exponential backoff and jitter」
在面試中說出這個短語,面試官就知道你懂分散式系統。
「抖動(jitter)」加入隨機性,防止大量客戶端在同一時間同步重試(thundering herd effect)。
冪等性(Idempotency)
冪等:同一操作執行多次,結果和執行一次相同。
| HTTP 方法 | 冪等 | 說明 |
|---|---|---|
| GET | ✅ | 讀取不改變狀態 |
| DELETE | ✅ | 刪了就是刪了 |
| PUT | ✅ | 覆寫結果相同 |
| POST | ❌ | 每次都可能建立新資源 |
| PATCH | ❌ | 取決於操作內容 |
冪等鍵(Idempotency Key) 讓非冪等操作變安全:
支付場景:
Client → POST /payments
headers: { "Idempotency-Key": "user_123_2026-04-20_purchase" }
Server:
if (已處理這個 key) → 回傳相同結果,不重複扣款
else → 處理並記錄 key
冪等鍵的組成公式
key = f(user_id, date, operation_type)
目的是讓同一個「意圖」的重試能被識別出來。
熔斷器(Circuit Breaker)
解決級聯故障(cascading failure):下游服務崩潰時,持續重試只會讓問題更嚴重。
三狀態機:
失敗超過閾值
Closed ──────────────► Open
(正常監控) (拒絕所有請求)
▲ │
│ │ 逾時到期(如 30 秒)
│ ▼
│ Half-Open
│ (放一個測試請求)
│ │ │
└──── 成功 ─────────┘ └──── 失敗 ──► 回到 Open
| 狀態 | 行為 |
|---|---|
| Closed(正常) | 監控失敗次數,一切正常通過 |
| Open(跳閘) | 立即拒絕請求,不嘗試實際呼叫,保護下游 |
| Half-Open(測試) | 逾時後放行一個測試請求,成功則復原,失敗則退回 Open |
熔斷器的優勢:
- 快速失敗:不等逾時,立即告知客戶端
- 減少下游壓力:避免「驚群效應(thundering herd)」
- 自動恢復:無需人工介入
- 改善用戶體驗:提供降級回應而非懸掛的 UI
何時在面試中提熔斷器
面試官問「如果這個服務掛掉怎辦?」或深挖可靠性、災難恢復時。
這是展示實際 oncall 經驗的好機會。
熔斷器適合的位置:
- 對第三方服務的外部 API 呼叫
- 資料庫連線和查詢
- 微服務間通訊
- 任何可能逾時的資源密集型操作
Related Notes
- 01-Networking/06-Load-Balancing — LB 的健康檢查也是一種故障處理
- 01-Networking/03-HTTP-and-HTTPS — HTTP 方法的冪等性
- 01-Networking/04-API-Paradigms — API 設計時需考慮冪等性
- 01-Networking/Practice-Networking