CAP 理論

原文鏈接:http://www.cnblogs.com/mmjx/archive/2011/12/19/2290540.html

CAP理論被很多人拿來作爲分佈式系統設計的金律,然而感覺大家對CAP這三個屬性的認識卻存在不少誤區。從CAP的證明中可以看出來,這個理論的成立是需要很明確的對C、A、P三個概念進行界定的前提下的。在本文中筆者希望可以對論文和一些參考資料進行總結並附帶一些思考。

 

一、什麼是CAP理論

CAP原本是一個猜想,2000年PODC大會的時候大牛Brewer提出的,他認爲在設計一個大規模可擴放的網絡服務時候會遇到三個特性:一致性(consistency)、可用性(Availability)、分區容錯(partition-tolerance)都需要的情景,然而這是不可能都實現的。之後在2003年的時候,Mit的Gilbert和Lynch就正式的證明了這三個特徵確實是不可以兼得的。

 

二、CAP的概念

Consistency、Availability、Partition-tolerance的提法是由Brewer提出的,而Gilbert和Lynch在證明的過程中改變了Consistency的概念,將其轉化爲Atomic。Gilbert認爲這裏所說的Consistency其實就是數據庫系統中提到的ACID的另一種表述:一個用戶請求要麼成功、要麼失敗,不能處於中間狀態(Atomic);一旦一個事務完成,將來的所有事務都必須基於這個完成後的狀態(Consistent);未完成的事務不會互相影響(Isolated);一旦一個事務完成,就是持久的(Durable)。

對於Availability,其概念沒有變化,指的是對於一個系統而言,所有的請求都應該‘成功’並且收到‘返回’。

對於Partition-tolerance,所指就是分佈式系統的容錯性。節點crash或者網絡分片都不應該導致一個分佈式系統停止服務。

 

三、基本CAP的證明思路

CAP的證明基於異步網絡,異步網絡也是反映了真實網絡中情況的模型。真實的網絡系統中,節點之間不可能保持同步,即便是時鐘也不可能保持同步,所有的節點依靠獲得的消息來進行本地計算和通訊。這個概念其實是相當強的,意味着任何超時判斷也是不可能的,因爲沒有共同的時間標準。之後我們會擴展CAP的證明到弱一點的異步網絡中,這個網絡中時鐘不完全一致,但是時鐘運行的步調是一致的,這種系統是允許節點做超時判斷的。

CAP的證明很簡單,假設兩個節點集{G1, G2},由於網絡分片導致G1和G2之間所有的通訊都斷開了,如果在G1中寫,在G2中讀剛寫的數據, G2中返回的值不可能G1中的寫值。由於A的要求,G2一定要返回這次讀請求,由於P的存在,導致C一定是不可滿足的。

 

四、CAP的擴展

CAP的證明使用了一些很強的假設,比如純粹的異步網絡,強的C、A、P要求。事實上,我們可以放鬆某些條件,從而達到妥協。

首先 —— 弱異步網絡模型

弱異步網絡模型中所有的節點都有一個時鐘,並且這些時鐘走的步調是一致的,雖然其絕對時間不一定相同,但是彼此的相對時間是固定的,這樣系統中的節點可以不僅僅根據收到的消息來決定自己的狀態,還可以使用時間來判斷狀態,比如超時什麼的。

在這種場景下,CAP假設依舊是成立的,證明跟上面很相似。

 

不可能的嘗試 —— 放鬆Availability或者Partition-tolerance

放棄Partition-tolerance意味着把所有的機器搬到一臺機器內部,或者放到一個要死大家一起死的機架上(當然機架也可能出現部分失效),這明顯違背了我們希望的scalability。

放棄Availability意味着,一旦系統中出現partition這樣的錯誤,系統直接停止服務,這是不能容忍的。

 

最後的選擇 —— 放鬆一致性

我們可以看出,證明CAP的關鍵在於對於一致性的強要求。在降低一致性的前提下,可以達到CAP的和諧共處,這也是現在大部分的分佈式存儲系統所採用的方式:Cassandra、Dynamo等。“Scalability is a bussness concern”是我們降低一致性而不是A和P的關鍵原因。

Brewer後來提出了BASE (Basically Available, Soft-state, Eventually consistent),作爲ACID的替代和補充。 

 

五、戰勝CAP

1,2008年9月CTO of atomikos寫了一篇文章“A CAP Solution (Proving Brewer Wrong)”,試圖達到CAP都得的效果。

這篇文章的核心內容就是放鬆Gilbert和Lynch證明中的限制:“系統必須同時達到CAP三個屬性”,放鬆到“系統可以不同時達到CAP,而是分時達到”。

Rules Beat CAP:

1) 儘量從數據庫中讀取數據,如果數據庫不能訪問,讀取緩存中的數據

2) 所有讀都必須有版本號

3) 來自客戶端的更新操作排隊等候執行,update必須包括導致這次更新的讀操作的版本信息

4) 分區數量足夠低的時候排隊等待的update操作開始執行,附帶的版本信息用來驗證update是否應該執行

5) 不管是確認還是取消更新,所有的結構都異步的發送給請求方

證明:

1) 系統保證了consistency,因爲所有的讀操作都是基於snapshot的,而不正確的update操作將被拒絕,不會導致錯誤執行

2) 系統保證了availability,因爲所有的讀一定會返回,而寫也一樣,雖然可能會因爲排隊而返回的比較慢

3) 系統允許節點失效

缺點:

1) 讀數據可能會不一致,因爲之前的寫還在排隊

2) partition必須在有限的時間內解決

3) update操作必須在所有的節點上保持同樣的順序

 

2, 2011年11月Twitter的首席工程師Nathan Marz寫了一篇文章,描述了他是如何試圖打敗CAP定理的: How to beat the CAP theorem

本文中,作者還是非常尊重CAP定律,並表示不是要“擊敗”CAP,而是嘗試對數據存儲系統進行重新設計,以可控的複雜度來實現CAP。

Marz認爲一個分佈式系統面臨CAP難題的兩大問題就是:在數據庫中如何使用不斷變化的數據,如何使用算法來更新數據庫中的數據。Marz提出了幾個由於雲計算的興起而改變的傳統概念:

1) 數據不存在update,只存在append操作。這樣就把對數據的處理由CRUD變爲CR

2) 所有的數據的操作就只剩下Create和Read。把Read作爲一個Query來處理,而一個Query就是一個對整個數據集執行一個函數操作。

在這樣的模型下,我們使用最終一致性的模型來處理數據,可以保證在P的情況下保證A。而所有的不一致性都可以通過重複進行Query去除掉。Martz認爲就是因爲要不斷的更新數據庫中的數據,再加上CAP,才導致那些即便使用最終一致性的系統也會變得無比複雜,需要用到向量時鐘、讀修復這種技術,而如果系統中不存在會改變的數據,所有的更新都作爲創建新數據的方式存在,讀數據轉化爲一次請求,這樣就可以避免最終一致性的複雜性,轉而擁抱CAP。

具體的做法這裏略過。

 

總結:

其實對於大規模分佈式系統來說,CAP是非常穩固的,可以擴展的地方也不多。

它很大程度上限制了大規模計算的能力,通過一些設計方式來繞過CAP管轄的區域或許是下一步大規模系統設計的關鍵。

 

 

--------------- 參考文獻 -----------------------

[1] Seth Gilbert and Nancy Lynch. 2002. Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. SIGACT News 33, 2 (June 2002), 51-59. DOI=10.1145/564585.564601 http://doi.acm.org/10.1145/564585.564601

[2] Guy Pardon, 2008, A CAP Solution (Proving Brewer Wrong), http://blog.atomikos.com/2008/09/a-cap-solution-proving-brewer-wrong/

[3] Werner Vogels, 2007, Availability & Consistency, http://www.infoq.com/presentations/availability-consistency

[4] Nathan Marz, 2011, How to beat the CAP theorem, http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章