CAP理論由Eric Brewer在ACM PODC會議上的主題報告中提出,這個理論是NoSQL數據管理系統構建的基礎,如下圖所示:
▲CAP理論
其中字母“C”、“A”、“P”分別代表以下三個特征:
·強一致性(Consistency)。系統在執行過某項操作后仍然處于一致的狀態。在分布式系統中,更新操作執行成功后所有的用戶都應該讀取到最新的值,這樣的系統被認為具有強一致性。
·可用性(Availability)。每一個操作總是能夠在一定的時間內返回結果,這里需要注意的是“一定時間內”和“返回結果”。
“一定時間內”是指,系統的結果必須在給定時間內返回,如果超時則被認為不可用。這是至關重要的。比如通過網上銀行的網絡支付功能購買物品。當等待了很長時間,如15分鐘,系統還是沒有返回任務操作結果,購買者一直處于等待狀態,那么購買者就不知道現在是否支付成功,還是需要進行其他操作。這樣當下次購買者再次使用網絡支付功能時必將心有余悸。
“返回結果”同樣非常重要。還是拿這個例子來說,假如購買者點擊支付之后很快出現了結果,但是結果卻是“java.lang.error……”之類的錯誤信息。這對于普通購買者來說相當于沒有返回任何結果。因為他仍舊不知道系統處于什么狀態,是支付成功還是失敗,或者需要重新操作。
·分區容錯性(Partition Tolerance)。分區容錯性可以理解為系統在存在網絡分區的情況下仍然可以接受請求(滿足一致性和可用性)。這里網絡分區是指由于某種原因網絡被分成若干個孤立的區域,而區域之間互不相通。還有一些人將分區容錯性理解為系統對節點動態加入和離開的處理能力,因為節點的加入和離開可以認為是集群內部的網絡分區。
CAP是在分布式環境中設計和部署系統時所要考慮的三個重要的系統需求。根據CAP理論,數據共享系統只能滿足這三個特性中的兩個,而不能同時滿足三個條件。因此系統設計者必須在這三個特性之間做出權衡。例如Amazon的Dynamo具有高可用性和分區容錯性但不支持強一致性,也就是說用戶不能立即看到其他用戶更新的內容。
下面通過圖示來解釋數據共享系統為什么不能同時滿足CAP理論三個條件。
如下圖所示,在網絡中有兩個節點分別為G1和G2,這兩個節點上存儲著同一數據的不同副本,現在數據是一致的,兩個副本的值都為V0,A、B分別是運行在G1、G2上與數據交互的應用程序。
▲網絡節點及數據分布圖
在正常情況下,操作過程如下(如下圖所示):
(1)A將V0更新,數據值為V1;
(2)G1發送消息m給G2,數據V0更新為V1;
(3)B讀取到G2中的數據V1。
▲正常情況
如果發生網絡分區故障,那么在操作的步驟(2)將發生錯誤:G1發送的消息不能傳送到G2上。這樣數據就處于不一致的狀態,B讀取到的就不是最新的數據,如圖2-3所示。如果我們采用一些技術如阻塞、加鎖、集中控制等來保證數據的一致,那么必然會影響到系統的可用性和分區容錯性。
▲網絡分區故障
CAP理論告訴我們如果系統具有較高的可用性和較小延遲,那么節點必須能夠容忍網絡分區,但這時候應用程序可能會得到不同的數據(B讀取到的值為V1)。
有人可能會想,如果我們對步驟(2)的操作加一個同步消息,問題會不會解決呢(同時滿足CAP理論三個特性)?答案是否定的。不加同步的情況下,G1到G2的更新是不可知的,也就是說,B讀取到得數據可能是V1也可能是V2,但是服務是可用的。即同時滿足了“A”和“P”,但是不保證“C”一定滿足。加了同步消息之后,將能夠保證B讀取到數據V1。但是這個同步操作必定要消耗一定的時間,尤其是在網絡規模較大的情況下,當節點規模成百上千的時候,不一定能保證此時的服務是可用的。這種情況下只能滿足“C”和“P”,而不能保證“A”一定滿足。
CAP理論不但對此網絡和通信模型有效,對其他模型同樣有效,有興趣的讀者可以換其他的網絡和通信模型來驗證CAP理論。
根據CAP理論,系統滿足三個條件中不同的兩個條件會具有不同的特點,見下表:處理CAP問題的選擇。
可以看出,三種不同的組合對應著放棄了CAP三個特性當中的一個。
·放棄P:如果想避免分區容錯性問題的發生,一種做法是將所有的數據(與事務相關的)都放到一臺機器上。雖然無法100%地保證系統不會出錯,但不會碰到由分區帶來的負面效果。當然,這個選擇會嚴重影響系統的擴展性。
·放棄A:相對于放棄“分區容錯性”來說,其反面就是放棄可用性。一旦遇到分區容錯故障,那么受到影響的服務需要等待數據一致,因此在等待期間系統就無法對外提供服務。
·放棄C:這里所說的放棄一致性,并不是完全放棄數據的一致性,而是放棄數據的強一致性,而保留數據的最終一致性。以網絡購物為例,對只剩最后一件庫存的商品,如果同時接收到了兩份訂單,那么較晚的訂單將被告知商品售罄。
·其他選擇:引入BASE(Basically Available, Soft-state, Eventually consistent),該方法支持最終一致性,其實是放棄C的一個特例,我們將在后文進行介紹。
傳統關系型數據管理系統注重數據的強一致性,但是對于海量數據的分布式存儲和處理其性能不能滿足人們的需求,因此現在許多NoSQL數據庫犧牲了強一致性來提高性能,CAP理論對于非關系性數據庫的設計有很大的影響并被NoSQL陣營所認可。
CAP理論已經得到人們的普遍認同,但是并不是所有人都這樣認為,這種不同的聲音主要是因為對CAP的概念有不同的理解所造成的。此外,我們不能說一種解決方案在任何時間任何環境下永遠都是正確的,因為隨著時間和環境的變遷情況將會有所不同,正如隨著海量數據的出現,傳統關系型數據庫已經不能完全滿足人們的需求一樣。因此,我們應該肯定CAP理論對海量數據管理的研究與發展所作出的貢獻。