CAP是Consistency(一致性),Availability(可用性),Partition tolerance(分區容錯性)的縮寫。在學習redis過程中看到這個名詞,查找各位大佬的文章發現這篇講得很簡單清晰,文章來自公眾號:codewill。
CAP 定理(CAP theorem)又被稱作布魯爾定理,是加州大學伯克利分校的計算機科學家埃里克·布魯爾(Eric Brewer)在 2000 年的 ACM PODC 上提出的一個猜想。2002 年,麻省理工學院的賽斯·吉爾伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)發表了布魯爾猜想的證明,使之成為分布式計算領域公認的一個定理。
對於設計分布式系統的架構師來說,CAP 是必須掌握的理論。
為了更好地解釋 CAP 理論,我特意去大佬的博客看了下,的文章作為參考基礎。(http://robertgreiner.com/about)
Robert Greiner 對 CAP 的理解也經歷了一個過程,他寫了兩篇文章來闡述 CAP 理論,第一篇被標記為“outdated”(網上絕大部分解鎖都止於第一篇)。
我們先看下第一版和第二版的差異
第一版
Any distributed system cannot guaranty C, A, and P simultaneously.
對於一個分布式計算系統,不可能同時滿足一致性(Consistence)、可用性(Availability)、分區容錯性(Partition Tolerance)三個設計約束。
1. 一致性(Consistency)
All nodes see the same data at the same time.
所有節點在同一時刻都能看到相同的數據。
2. 可用性(Availability)
Every request gets a response on success/failure.
每個請求都能得到成功或者失敗的響應。
3. 分區容忍性(Partition Tolerance)
System continues to work despite message loss or partial failure.
出現消息丟失或者分區錯誤時系統能夠繼續運行。
第二版
In a distributed system (a collection of interconnected nodes that share data.), you can only have two out of the following three guarantees across a write/read pair: Consistency, Availability, and Partition Tolerance - one of them must be sacrificed.
在一個分布式系統(指互相連接並共享數據的節點的集合)中,當涉及讀寫操作時,只能保證一致性(Consistence)、可用性(Availability)、分區容錯性(Partition Tolerance)三者中的兩個,另外一個必須被犧牲。
1. 一致性(Consistency)
A read is guaranteed to return the most recent write for a given client.
對某個指定的客戶端來說,讀操作保證能夠返回最新的寫操作結果。
2. 可用性(Availability)
A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout).
非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。
3. 分區容忍性(Partition Tolerance)
System continues to work despite message loss or partial failure.
當出現網絡分區后,系統能夠繼續“履行職責”。
我們來詳細看下具體的差異
首先概念上第二版定義了什么才是 CAP 理論探討的分布式系統,強調了兩點:interconnected 和 share data,為何要強調這兩點呢? 因為分布式系統並不一定會互聯和共享數據。最簡單的例如 Memcache 的集群,相互之間就沒有連接和共享數據,因此 Memcache 集群這類分布式系統就不符合 CAP 理論探討的對象;而 MySQL 集群就是互聯和進行數據復制的,因此是 CAP 理論探討的對象。
第二版強調了 write/read pair,這點其實是和上一個差異點一脈相承的。也就是說,CAP 關注的是對數據的讀寫操作,而不是分布式系統的所有功能。例如,ZooKeeper 的選舉機制就不是 CAP 探討的對象。
1. 一致性(Consistency)
第一版強調同一時刻擁有相同數據(same time + same data),第二版並沒有強調這點。
因此第一版的解釋“All nodes see the same data at the same time”是不嚴謹的。而第二版強調 client 讀操作能夠獲取最新的寫結果就沒有問題,因為事務在執行過程中,client 是無法讀取到未提交的數據的,只有等到事務提交后,client 才能讀取到事務寫入的數據,而如果事務失敗則會進行回滾,client 也不會讀取到事務中間寫入的數據。
2. 可用性(Availability)
第一版的 success/failure 的定義太泛了,幾乎任何情況,無論是否符合 CAP 理論,我們都可以說請求成功和失敗,因為超時也算失敗、錯誤也算失敗、異常也算失敗、結果不正確也算失敗;即使是成功的響應,也不一定是正確的。例如,本來應該返回 100,但實際上返回了 90,這就是成功的響應,但並沒有得到正確的結果。相比之下,第二版的解釋明確了不能超時、不能出錯,結果是合理的,
3. 分區容忍性(Partition Tolerance)
第一版用的是 work,第二版用的是 function。
work 強調“運行”,只要系統不宕機,我們都可以說系統在 work,返回錯誤也是 work,拒絕服務也是 work;而 function 強調“發揮作用”“履行職責”,這點和可用性是一脈相承的。也就是說,只有返回 reasonable response 才是 function。相比之下,第二版解釋更加明確。
CAP到底改怎么選
雖然 CAP 理論定義是三個要素中只能取兩個,但放到分布式環境下來思考,我們會發現必須選擇 P(分區容忍)要素,因為網絡本身無法做到 100% 可靠,有可能出故障,所以分區是一個必然的現象。如果我們選擇了 CA 而放棄了 P,那么當發生分區現象時,為了保證 C,系統需要禁止寫入,當有寫入請求時,系統返回 error(例如,當前系統不允許寫入),這又和 A 沖突了,因為 A 要求返回 no error 和 no timeout。因此,分布式系統理論上不可能選擇 CA 架構,只能選擇 CP 或者 AP 架構。
讓我們舉個栗子
1.CP - Consistency/Partition Tolerance
如下圖所示,為了保證一致性,當發生分區現象后, 節點1上的數據無法同步到 節點2, 節點2上的數據還是 Y。這時客戶端 C 訪問 節點2時,節點2 需要返回 Error,提示客戶端 “系統現在發生了錯誤”,這種處理方式違背了可用性(Availability)的要求,因此 CAP 三者只能滿足 CP。
2.AP - Availability/Partition Tolerance
如下圖所示,為了保證可用性,當發生分區現象后, 節點1上的數據無法同步到 節點2, 節點2上的數據還是 Y。這時客戶端 訪問 節點2 時,節點2 將當前自己擁有的數據 Y 返回給客戶端,而實際上當前最新的數據已經是 X了,這就不滿足一致性(Consistency)的要求了,因此 CAP 三者只能滿足 AP。