根據百度百科的定義,CAP定理又稱CAP原則,指的是在一個分佈式系統中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性),最多隻能同時三個特性中的兩個,三者不可兼得。html
1、CAP的定義
Consistency (一致性):node
「all nodes see the same data at the same time」,即更新操做成功並返回客戶端後,全部節點在同一時間的數據徹底一致,這就是分佈式的一致性。一致性的問題在併發系統中不可避免,對於客戶端來講,一致性指的是併發訪問時更新過的數據如何獲取的問題。從服務端來看,則是更新如何複製分佈到整個系統,以保證數據最終一致。sql
Availability (可用性):數據庫
可用性指「Reads and writes always succeed」,即服務一直可用,並且是正常響應時間。好的可用性主要是指系統可以很好的爲用戶服務,不出現用戶操做失敗或者訪問超時等用戶體驗很差的狀況。緩存
Partition Tolerance (分區容錯性):服務器
即分佈式系統在遇到某節點或網絡分區故障的時候,仍然可以對外提供知足一致性和可用性的服務。網絡
分區容錯性要求可以使應用雖然是一個分佈式系統,而看上去卻好像是在一個能夠運轉正常的總體。好比如今的分佈式系統中有某一個或者幾個機器宕掉了,其餘剩下的機器還可以正常運轉知足系統需求,對於用戶而言並無什麼體驗上的影響。併發
上圖中,G1 和 G2 是兩臺跨區的服務器。G1 向 G2 發送一條消息,G2 可能沒法收到。系統設計的時候,必須考慮到這種狀況。異步
通常來講,分區容錯沒法避免,所以能夠認爲 CAP 的 P 老是成立。CAP 定理告訴咱們,剩下的 C 和 A 沒法同時作到nosql
先看 Partition tolerance,中文叫作"分區容錯"。
大多數分佈式系統都分佈在多個子網絡。每一個子網絡就叫作一個區(partition)。分區容錯的意思是,區間通訊可能失敗。好比,一臺服務器放在中國,另外一臺服務器放在美國,這就是兩個區,它們之間可能沒法通訊。
上圖中,G1 和 G2 是兩臺跨區的服務器。G1 向 G2 發送一條消息,G2 可能沒法收到。系統設計的時候,必須考慮到這種狀況。
通常來講,分區容錯沒法避免,所以能夠認爲 CAP 的 P 老是成立。CAP 定理告訴咱們,剩下的 C 和 A 沒法同時作到。
Consistency 中文叫作"一致性"。意思是,寫操做以後的讀操做,必須返回該值。舉例來講,某條記錄是 v0,用戶向 G1 發起一個寫操做,將其改成 v1。
接下來,用戶的讀操做就會獲得 v1。這就叫一致性。
問題是,用戶有可能向 G2 發起讀操做,因爲 G2 的值沒有發生變化,所以返回的是 v0。G1 和 G2 讀操做的結果不一致,這就不知足一致性了。
爲了讓 G2 也能變爲 v1,就要在 G1 寫操做的時候,讓 G1 向 G2 發送一條消息,要求 G2 也改爲 v1。
這樣的話,用戶向 G2 發起讀操做,也能獲得 v1。
Availability 中文叫作"可用性",意思是隻要收到用戶的請求,服務器就必須給出迴應。
用戶能夠選擇向 G1 或 G2 發起讀操做。不論是哪臺服務器,只要收到請求,就必須告訴用戶,究竟是 v0 仍是 v1,不然就不知足可用性。
一致性和可用性,爲何不可能同時成立?答案很簡單,由於可能通訊失敗(即出現分區容錯)。
若是保證 G2 的一致性,那麼 G1 必須在寫操做時,鎖定 G2 的讀操做和寫操做。只有數據同步後,才能從新開放讀寫。鎖按期間,G2 不能讀寫,沒有可用性不。
若是保證 G2 的可用性,那麼勢必不能鎖定 G2,因此一致性不成立。
綜上所述,G2 沒法同時作到一致性和可用性。系統設計時只能選擇一個目標。若是追求一致性,那麼沒法保證全部節點的可用性;若是追求全部節點的可用性,那就無法作到一致性。
讀者問,在什麼場合,可用性高於一致性?
舉例來講,發佈一張網頁到 CDN,多個服務器有這張網頁的副本。後來發現一個錯誤,須要更新網頁,這時只能每一個服務器都更新一遍。
通常來講,網頁的更新不是特別強調一致性。短時期內,一些用戶拿到老版本,另外一些用戶拿到新版本,問題不會特別大。固然,全部人最終都會看到新版本。因此,這個場合就是可用性高於一致性。
CAP三個特性只能知足其中兩個,那麼取捨的策略就共有三種:
CA without P:若是不要求P(不容許分區),則C(強一致性)和A(可用性)是能夠保證的。但放棄P的同時也就意味着放棄了系統的擴展性,也就是分佈式節點受限,沒辦法部署子節點,這是違背分佈式系統設計的初衷的。
CP without A:若是不要求A(可用),至關於每一個請求都須要在服務器之間保持強一致,而P(分區)會致使同步時間無限延長(也就是等待數據同步完才能正常訪問服務),一旦發生網絡故障或者消息丟失等狀況,就要犧牲用戶的體驗,等待全部數據所有一致了以後再讓用戶訪問系統。設計成CP的系統其實很多,最典型的就是分佈式數據庫,如Redis、HBase等。對於這些分佈式數據庫來講,數據的一致性是最基本的要求,由於若是連這個標準都達不到,那麼直接採用關係型數據庫就好,不必再浪費資源來部署分佈式數據庫。
舉例來講,發佈一張網頁到 CDN,多個服務器有這張網頁的副本。後來發現一個錯誤,須要更新網頁,這時只能每一個服務器都更新一遍。
通常來講,網頁的更新不是特別強調一致性。短時期內,一些用戶拿到老版本,另外一些用戶拿到新版本,問題不會特別大。固然,全部人最終都會看到新版本。因此,這個場合就是可用性高於一致性。
AP wihtout C:要高可用並容許分區,則需放棄一致性。一旦分區發生,節點之間可能會失去聯繫,爲了高可用,每一個節點只能用本地數據提供服務,而這樣會致使全局數據的不一致性。典型的應用就如某米的搶購手機場景,可能前幾秒你瀏覽商品的時候頁面提示是有庫存的,當你選擇完商品準備下單的時候,系統提示你下單失敗,商品已售完。這其實就是先在 A(可用性)方面保證系統能夠正常的服務,而後在數據的一致性方面作了些犧牲,雖然多少會影響一些用戶體驗,但也不至於形成用戶購物流程的嚴重阻塞。
舉例來講,拿銀行的轉帳系統來講,涉及到金錢的對於數據一致性不能作出一絲的讓步,C必須保證,出現網絡故障的話,寧肯中止服務
一、知足一致性,可用性的系統,一般在可擴展性上不太強大,例以下面的產品:
Traditional RDBMSs like Postgres,MySQL, etc (relational)
Vertica (column-oriented)
Aster Data (relational)
Greenplum (relational)
二、知足一致性,分區容忍必的系統,一般用戶操做響應上不太穩定,例以下面的產品:
BigTable (column-oriented/tabular)
Hypertable (column-oriented/tabular)
HBase (column-oriented/tabular)
MongoDB (document-oriented)
Terrastore (document-oriented)
Redis (key-value)
Scalaris (key-value)
MemcacheDB (key-value)
Berkeley DB (key-value)
三、知足可用性,分區容忍性的系統,一般可能對一致性要求低一些,例以下面的產品:
Dynamo (key-value)
Voldemort (key-value)
Tokyo Cabinet (key-value)
KAI (key-value)
Cassandra (column-oriented/tabular)
CouchDB (document-oriented)
SimpleDB (document-oriented)
Riak (document-oriented)
Guy Pardon寫了一篇文章「A CAP Solution (Proving Brewer Wrong)」來反對CAP理論。他提出了一個同時知足CAP的解決方案來反對Brewer的三者只能取其二的說法。
他設計的系統以下:
(1)程序若是可以讀取數據庫的話讀取數據庫,若是不能的話可使用緩存代替。
(2)全部的讀取操做使用版本號或者其餘可使用樂觀鎖的機制。
(3)客戶端的全部更新操做所有放在隊列中順序處理。更新操做中要包括該更新的讀取操做時的版本信息。
(4)當分區數量足夠少的時候,能夠處理隊列中的更新操做。比較簡單的方式是創建一個跨越全部分佈式副本的事務,對每一個副本進行更新操做(其餘方式好比quorum等等也能夠)。若是該更新的讀取操做時的版本信息不是當前數據庫中數據的版本信息,則將失敗返回給客戶端,不然返回成功。
(5)數據庫操做結果(確認或者取消)經過異步的方式發送到客戶端,能夠經過郵件,消息隊列或者其餘異步方式。
該系統符合CAP以下:
符合C(高一致性):讀取的數據都是基於快照的,並且錯誤的更新操做不會執行。
符合A(高可用性):讀取和更新都會返回數據。
符合P(高分區容錯性):容許網絡或者節點出錯。
該設計是符合BASE理論的。
參考資料:
http://www.julianbrowne.com/article/viewer/brewers-cap-theorem
http://www.sigma.me/2011/06/13/NoSQL-CAP-Theorem.html
http://blog.nosqlfan.com/html/1112.html
http://guysblogspot.blogspot.com/2008/09/cap-solution-proving-brewer-wrong.html
https://blog.csdn.net/godfrey90/article/details/6754884