系統設計中的 CAP 理論
當從單體應用程式 (Monolithic Application) 走向微服務或任何分散式架構時,享受了擴展性與彈性的好處,但也必須面對一個新的挑戰:如何在多個節點之間維持資料的可靠性與服務的可用性?
想像一下這個場景:在一個全球知名的電商平台搶購限量版球鞋。當按下「購買」的瞬間,系統背後可能有數十甚至數百台伺服器在同時運作。系統如何確保你買到的這雙鞋不會同時被另一個人買走?又如何保證即使某個地區的機房發生網路問題,依然能順利完成交易?
這就是 CAP 理論要解決的核心問題。
在分散式系統設計中,CAP 理論(CAP Theorem)是一個核心概念,用來描述在分散式資料庫中,系統無法同時滿足 一致性(Consistency)、可用性(Availability)、分區容錯性(Partition Tolerance) 這三大特性。理解 CAP 理論對於後端工程師在設計資料庫架構或分散式系統時至關重要。
什麼是 CAP 理論?
CAP 理論,又稱布魯爾定理 (Brewer’s Theorem),由電腦科學家 Eric Brewer 在 2000 年提出。它指出,任何一個分散式資料儲存系統,最多只能同時滿足以下三個特性中的兩項。
在一個分散式系統中,一致性 (Consistency)、可用性 (Availability) 和 分區容錯性 (Partition Tolerance),這三者無法兼得。
CAP 三大特性
1. 一致性(Consistency)
-
定義:所有節點在同一時間點讀取到的資料,必須是完全相同的。
-
白話解釋:當成功寫入一筆新資料後,任何後續的讀取操作,都應該要能讀到這筆最新的資料。系統就像只有一個「真相」來源,絕不允許讀到舊的或不一致的資料。
-
優點:避免資料不同步問題,提供強一致性體驗。
-
缺點:可能需要等待資料同步完成,導致延遲。
2. 可用性(Availability)
-
定義:每一次的請求,不論是讀取或寫入,都必須收到一個(非錯誤的)回應。
-
白話解釋:系統永遠處於「開機」狀態。只要使用者發出請求,系統就一定會回應,它不能因為內部忙碌或網路問題就直接拋出錯誤或無止盡地等待。不過,它不保證回傳的資料是最新的。
-
優點:系統可靠、不間斷服務。
-
缺點:可能回傳舊資料,導致一致性下降。
3. 分區容錯性(Partition Tolerance)
-
定義:即使叢集中的部分節點之間因為網路問題而無法互相通訊(也就是發生「網路分區」),系統整體仍然能夠繼續運作。
-
白話解釋:在現代雲端架構中,網路閃爍、交換機故障、機房斷線是家常便飯。分區容錯性意味著系統設計必須能容忍這些意外,不能因為兩個節點「失聯」就導致整個系統崩潰。
-
優點:保證系統在網路異常下仍能運行。
-
缺點:必須在一致性與可用性之間做取捨。
CAP 不可能三角
CAP 理論指出,在發生網路分區的情況下,系統只能同時滿足 一致性(C) 和 可用性(A) 其中之一,而無法同時兼顧。這就是所謂的 「不可能三角」。
用圖來表示如下:
graph TD
C[一致性<br>Consistency] --- A[可用性<br>Availability]
A --- P[分區容錯性<br>Partition Tolerance]
P --- C
style C fill:#d6f0ff,stroke:#3399ff,stroke-width:2px
style A fill:#d6f0ff,stroke:#3399ff,stroke-width:2px
style P fill:#d6f0ff,stroke:#3399ff,stroke-width:2px
CAP 理論最關鍵的部分在於:P (分區容錯性) 在現今的分散式系統中,是一個「必選項」,而不是「可選項」。
只要系統部署在多台機器上,就必須假設網路隨時可能出問題。因此,系統設計的真正權衡,其實是在網路分區發生時,必須在 C (一致性) 和 A (可用性) 之間做出抉擇。
用一個簡單的圖示來思考:
[資料庫節點 A] <---- 網路連線正常 ----> [資料庫節點 B]
(資料: v1) (資料: v1)
假設此時,一個寫入請求進來,將資料更新為 v2
。資料成功寫入節點 A,並開始同步到節點 B。
[資料庫節點 A] <---- 同步中 ----> [資料庫節點 B]
(資料: v2) (資料: v1)
就在這個瞬間,網路發生了分區!
[資料庫節點 A] <---- X 網路中斷 X ----> [資料庫節點 B]
(資料: v2) (資料: v1)
現在,一個讀取請求進來了,它可以被路由到節點 A 或節點 B。這時面臨了抉擇:
-
選擇 C (一致性),放棄 A (可用性) - 稱為 CP 系統
- 為了保證一致性,節點 B 因為無法與節點 A 同步以獲取最新的
v2
資料,它必須拒絕所有的讀取請求,或者回傳錯誤。 - 這樣做確保了任何讀取請求都不會讀到舊的資料 (
v1
),維持了資料的強一致性。但犧牲了節點 B 的可用性。
- 為了保證一致性,節點 B 因為無法與節點 A 同步以獲取最新的
-
選擇 A (可用性),放棄 C (一致性) - 稱為 AP 系統
- 為了保證可用性,節點 B 即使知道自己可能不是最新的,它仍然會回傳它目前擁有的資料 (
v1
)。 - 這樣做確保了系統永遠可以回應使用者的請求,但犧牲了資料的一致性(使用者可能會讀到舊資料)。
- 為了保證可用性,節點 B 即使知道自己可能不是最新的,它仍然會回傳它目前擁有的資料 (
現實世界的例子
CP 系統 (Consistency > Availability)
當資料的正確性至關重要,不容許絲毫偏差時,就會選擇 CP。
- 應用場景:銀行交易、金融系統、訂單管理。絕對不希望因為讀到舊的餘額資料而造成超額提款,或因為庫存資料不一致而超賣商品。
- 代表技術:MongoDB、Redis、HBase。這些系統都提供了調整一致性等級的選項,在需要時可以配置為強一致性模式。
AP 系統 (Availability > Consistency)
當使用者體驗和系統的永遠在線比短暫的資料不一致更重要時,就會選擇 AP。
- 應用場景:社群媒體的按讚數、貼文瀏覽次數、電商網站的商品評論。晚幾秒鐘看到最新的按讚數不會造成嚴重後果,但如果網站頻繁顯示錯誤訊息,使用者會立刻流失。
- 代表技術:Cassandra、DynamoDB (Amazon)、CouchDB。它們天生就是為了高可用性和高擴展性而設計的,採用的是「最終一致性」(Eventual Consistency) 模型。
那 CA 系統呢?
理論上,一個沒有分區容錯需求的系統就是 CA 系統。這意味著什麼?它只有一個節點!傳統的單體關聯式資料庫(如 MySQL、PostgreSQL)可以被視為 CA 系統。它們在單機內保證了強大的 ACID 一致性與可用性,但一旦這台機器掛了,或是網路斷了,整個系統就無法服務了。這在分散式架構中是不可行的。
結論
CAP 理論不是一個僵硬的規則,而是一個幫助我們理解分散式系統設計權衡的框架。它提醒我們:
- 在分散式世界裡,網路分區 (P) 是必然的,必須為它設計。
- 你的選擇是在發生分區時,要 犧牲一致性 © 還是可用性 (A)。
- 這個選擇沒有絕對的好壞,完全取決於業務需求。問問自己:是「絕對不能出錯的資料」比較重要,還是「永不中斷的服務」比較重要?
在設計分散式系統時,不可能同時兼顧 一致性、可用性、分區容錯性 三者,只能依照應用場景做出取捨。
- 金融或高敏感度資料 → CP 系統
- 高可用、用戶體驗優先 → AP 系統
- 小型單機系統 → CA 系統
理解 CAP 理論,能幫助我們在不同業務需求下選擇合適的架構,設計更可靠與合理的分散式系統。