CAP的理解我也看了不少書籍,也看了很多同行的博文,基本每一個人的理解都不同,而布魯爾教授得定義又太過的簡單,沒有具體描述和場景案例分析。所以本身參考部分資料梳理了一篇與你們互相分享一下。node
標題寫了正確理解,或許某些點不是百分百正確或者有歧義,可是但願與各位分享討論後達到最終正確,web
CAP定理,又被稱做布魯爾定理(Brewer's theorem),是埃裏克·布魯爾教授在2000 年提出的一個猜測,它指出對於一個分佈式系統來講,不可能同時知足如下三點:redis
不少書籍與文章引用Robert Greiner在2014年8月寫的一篇博文 http://robertgreiner.com/2014/08/cap-theorem-revisited/。相比與看着布魯爾教授一臉懵逼的定義,Robert Greiner的更加容易理解。sql
原文: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)三者中的兩個,另一個必須被犧牲。網絡
關鍵字:interconnected nodes(互連節點)、share data(共享數據)、a write/read pair(讀/寫)session
從上面一段話,有幾個,也就是說咱們聊CAP定理的時候,是在具備數據讀寫、數據共享和節點互連的前提下,對上面三者選其二,也是建議咱們不要花費時間與精力同時知足三者。分佈式
舉例說明,web集羣、memcached集羣不屬於討論對象memcached
總得來講,CAP定理討論的並非分佈式系統全部的功能。翻譯
原文:A read is guaranteed to return the most recent write for a given client.
翻譯:對某個指定的客戶端來講,讀操做保證可以返回最新的寫操做結果
關鍵字:a given client(指定的客戶端)。
這裏的一致性與咱們日常瞭解ACID的一致性有點誤差,ACID的一致性關注的是數據庫的數據完整性。
上面定義沒說明是全部節點必須在同一時間數據一致,而關注點在客戶端,假若有個場景,您在ATM(客戶端)往某張銀行卡存500元后,馬上在ATM發起查詢餘額的時候會顯示加了500元后的餘額,隨後咱們也能把這500元取出來。查詢餘額讀操做能夠是寫後馬上讀的主庫,也或者寫後某個時間段事後(中途無寫)讀從庫。
原文:A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout).
翻譯:非故障節點將在合理的時間內返回合理的響應(不是錯誤或超時)。
關鍵字:non-failing node(非故障節點)、reasonable response(合理的響應)
這裏的可用性和咱們日常所理解的高可用性有點誤差,高可用性指系統無中斷的執行其功能的能力。
已故障的節點就不具備可用性了,由於請求結果要麼error要麼 timeout。合理的響應沒有說明是成功仍是失敗,可是響應應該具備是否成功的精確描述。例如咱們讀取sql server集羣的某從庫,同步須要時間,讀取出來可能不是最新的數據,但倒是合理的響應。
原文:The system will continue to function when network partitions occur.
翻譯:當網絡分區發生時,系統將繼續正常運做
關鍵字:continue to function(繼續正常運做)
假如作了一個redis的一主兩從的集羣,某天某個從節點由於網絡故障變成不可用,可是另外的一主一從仍然能正常運做,那麼咱們認爲它具備分區容錯性。
做爲分佈式系統,分區必然總會發生(2年1次50分鐘仍是1年3次共10分鐘?),所以認爲CAP的討論是大部分創建在P確立前提下。假設咱們犧牲了P這個時候由於網絡故障發生了分區致使節點不可用,這個時候請求響應了error、timeout,與可用性的定義相沖突了。
可是,咱們又假如分區大部分時間是不存在的,這時對單節點的讀\寫,那麼就無需做出C、A的取捨。可是上面說分區總會發生這不互相矛盾麼,仍是取捨。假如1年時間內99.99%時間是正常的,不可用時間爲0.01%(52.56分鐘)不可用,若這個時間屬於業務接受範圍,或者只在某個地區(華南、華北、華中?)有影響,那麼CA也是能夠選擇的。
最典型的案例是RDBMS集羣與Redis集羣,這兩種都是利用主從複製實現讀寫分離的方案。假如二者都是創建一主多從的集羣,在主節點寫入數據,爲了保證隨後的讀操做獲取最新數據(一致性),這個讀操做仍會請求主節點(讀寫分離的複雜點在從庫同步不及時致使業務的異常,爲了保證業務的正常性寫後的讀會請求主庫),某個從節點掛了可是隻要主節點和其餘從節點仍然正常運做,就知足分區容錯性。可是哪天主節點由於網絡故障致使寫操做的error或者timeout,那麼這個系統就不可用了(犧牲可用性)。
這個時候能夠引入其餘功能和機制完成,例如Redis哨兵模式、故障轉移功能。
最典型的案例是Cassanda集羣和Riak集羣,這種類型的分佈式數據庫,能夠任意節點寫入,任意節點讀取,看成爲集羣出現,不管寫入哪一個節點,都將會把該節點的數據同步到其餘節點上,由於這種同步方式,讀取數據時只要訪問一個節點就足夠了(喜歡任意訪問也不攔着你),可是由於其餘節點數據同步緣由,數據可能並非最新的(犧牲一致性)。若是當前節點由於網絡異常致使分區變得不可用(不管讀\寫),能夠轉移訪問節點(可用性)。
另外這裏說的犧牲一致性,並不表明放棄一致性,而PA選擇的是最終一致性(系統中全部的數據副本,在通過一段時間的同步後,最終可以達到一個一致的狀態)
上面涉及「犧牲」字眼,並不表明非此即彼的選擇,能夠根據子系統、模塊之間的設計上進行混搭使用(例如PA和PC、CA和PC)。
本文對CAP定理作了一個簡單的梳理描述,參考了部分書籍和文章加上本身的理解但願能夠跟你們作個分享,若是有不一樣建議和見解包括文章內描述錯誤,請在下方評論指出,我將及時做出修改。