8 條 Fallacies of Distributed Computing

Peter Deutsch(和 James Gosling 等人)1994 年提出,原文列了 8 條常見的錯誤假設:

1. 網路是可靠的

現實:網路會超時、丟包、暫時中斷。同一個 datacenter 內也會。

後果:你呼叫了外部 API,沒有收到回應——是成功了還是失敗了?你不知道。這就是 timeout 問題,也是為什麼需要 idempotency key。

2. 延遲是零

現實:即使是同 datacenter 的網路呼叫也有 0.55ms 的延遲;跨 region 是 100300ms;衛星網路是 600ms+。

後果:把遠端 API 呼叫當成本地函式呼叫設計,串了 20 個 service call,結果每個 request 要花 5 秒。需要 parallelization、batching、或把資料挪近(CQRS / 快取)。

3. 頻寬是無限的

現實:大量資料傳輸有成本,跨雲費用更高,而且壓力下頻寬真的會成為瓶頸。

後果:把完整物件序列化後傳來傳去,而不是只傳需要的欄位。gRPC + Protobuf 的一大好處是比 JSON 小 3-5 倍。

4. 網路是安全的

現實:內網也可能被 compromised,服務之間的通訊不應該假設可信。

後果:Zero Trust 架構存在的原因——即使是 internal service,也要驗證身份和授權。

5. 拓撲是固定的

現實:IP 會變,load balancer 後面的 instance 會上下線,服務會遷移。

後果:硬寫 IP 位址,而不是用 DNS / Service Discovery。Container 世界裡 IP 每次部署都會換。

6. 只有一個管理員

現實:分散式系統有多個 team 管理不同部分,沒有人完全了解全貌。

後果:假設有人會統一維護所有 schema 和 API contract。實際上需要 API versioning、backward compatibility、contract testing。

7. 傳輸成本是零

現實:序列化 / 反序列化有 CPU 成本;跨 AZ / region 有網路費用;HTTP 框架有額外 overhead。

後果:微服務拆得過細,每個請求都要跨 10 個 service,serialization overhead 加起來比計算本身還多。

8. 網路是同質的

現實:系統裡有不同的網路設備、協議版本、MTU 大小、防火牆規則。

後果:在自己的環境測過了,但某個客戶的網路設備不支援 HTTP/2,或者防火牆擋了某個 port。


Split-Brain:最嚴重的分散式故障

Split-Brain 是指:網路 partition 導致兩組節點各自以為對方掛了,然後都選出自己的 Leader,形成兩個各自接受寫入的主節點——資料分裂。

原本:                    Network Partition:
  Leader A                  Group 1: A (認為是 Leader)
  Follower B                Group 2: B, C (選出新 Leader B)
  Follower C
                        兩個 Leader 同時接受寫入 → 資料衝突

解法:Fencing Token(防止舊 Leader 繼續寫入)、STONITH(Shoot The Other Node In The Head,強制關掉可疑的舊 Leader)、Quorum(多數派才能成為 Leader)。


Retry 和 Idempotency

網路不可靠,所以需要 retry。但 retry 帶來新問題:如果原始請求其實成功了,只是 response 遺失了呢?

冪等性(Idempotency):同一個操作執行多次的結果和執行一次相同。

冪等:GET(查詢)、DELETE(刪除),PUT(覆寫,不是 patch)
不冪等:POST(每次都可能建新資料)

讓 POST 冪等的方法:使用 Idempotency Key
POST /transfers
Idempotency-Key: abc-123-unique-key
{ "amount": 100, "to": "account-B" }

同樣的 Idempotency-Key 重複送,server 返回第一次的結果,不重複執行
Stripe、Braintree 等支付 API 都有這個機制

應用開發者的實際應對清單

  • 所有外部呼叫加 timeout,不要用 library 的無限等待預設
  • 重要操作加 Idempotency Key,讓 retry 安全
  • 不要硬寫 IP,用 DNS 或 Service Discovery(Consul、Kubernetes Service)
  • 服務之間加 circuit breaker(Resilience4j、Hystrix),避免一個 service 慢導致全部堆積
  • 設計時假設 downstream 會掛,加 fallback 和 graceful degradation
  • 內網也做認證,不要信任來源 IP