CAP 理論常被解釋為一種「三選二」定律,這是否是一種誤解?

此處的 CAP 理論指的是計算機科學中分散式系統領域的一條已經證明的定律。參見:

CAP theorem - Wikipedia

我對這個定律的證明沒有疑慮。但現實生活中,大部分人解釋這一定律時,常常簡單的表述為:「一致性、可用性、分區容忍性三者你只能同時達到其中兩個,不可能同時達到」

這是否符合 CAP 定律的本意?這樣的描述是否存在誤解?

謝謝每一位回答者。


是的,這是一種誤解。注意 CAP 定律的完整表述:Any networked shared-data system can have at most two of the three desired properties.

換句話說, CAP 定律的前提是 P,當 P 決定後才有 CA 的抉擇。因此,簡單粗暴地說「三選二」是有一定誤導性的。

其實這個問題早在 2012 年就已經被詳細解釋過了[1],這裡已經說得很好了,下面是引用[2]:

為什麼「三選二」公式有誤導性

理解CAP理論的最簡單方式是想像兩個節點分處分區兩側。允許至少一個節點更新狀態會導致數據不一致,即喪失了C性質。如果為了保證數據一致性,將分區一側的節點設置為不可用,那麼又喪失了A性質。除非兩個節點可以互相通信,才能既保證C又保證A,這又會導致喪失P性質。一般來說跨區域的系統,設計師無法捨棄P性質,那麼就只能在數據一致性和可用性上做一個艱難選擇。不確切地說,NoSQL運動的主題其實是創造各種可用性優先、數據一致性其次的方案;而傳統資料庫堅守ACID特性(原子性、一致性、隔離性、持久性),做的是相反的事情。下文「ACID、BASE、CAP」小節詳細說明了它們的差異。

事實上,CAP理論本身就是在類似的討論中誕生的。早在1990年代中期,我和同事構建了一系列的基於集群的跨區域系統(實質上是早期的雲計算),包括搜索引擎、緩存代理以及內容分發系統。從收入目標以及合約規定來講,系統可用性是首要目標,因而我們常規會使用緩存或者事後校核更新日誌來優化系統的可用性。儘管這些策略提升了系統的可用性,但這是以犧牲系統數據一致性為代價的。

關於「數據一致性 VS 可用性」的第一回合爭論,表現為ACID與BASE之爭。當時BASE還不怎麼被人們接受,主要是大家看重ACID的優點而不願意放棄。提出CAP理論,目的是證明有必要開拓更廣闊的設計空間,因此才有了「三選二」公式。CAP理論最早在1998年秋季提出,1999年正式發表,並在2000年登上Symposium on Principles of Distributed Computing大會的主題演講,最終確立了該理論的正確性。

「三選二」的觀點在幾個方面起了誤導作用。首先,由於分區很少發生,那麼在系統不存在分區的情況下沒什麼理由犧牲C或A。其次,C與A之間的取捨可以在同一系統內以非常細小的粒度反覆發生,而每一次的決策可能因為具體的操作,乃至因為牽涉到特定的數據或用戶而有所不同。最後,這三種性質都可以在程度上衡量,並不是非黑即白的有或無。可用性顯然是在0%到100%之間連續變化的,一致性分很多級別,連分區也可以細分為不同含義,如系統內的不同部分對於是否存在分區可以有不一樣的認知。

要探索這些細微的差別,就要突破傳統的分區處理方式,而這是一項根本性的挑戰。因為分區很少出現,CAP在大多數時候允許完美的C和A。但當分區存在或可感知其影響的情況下,就要預備一種策略去探知分區並顯式處理其影響。這樣的策略應分為三個步驟:探知分區發生,進入顯式的分區模式以限制某些操作,啟動恢復過程以恢複數據一致性並補償分區期間發生的錯誤。

進一步閱讀

  • [1] CAP Twelve Years Later: How the "Rules" Have Changed
  • [2] 中譯:CAP理論十二年回顧:"規則"變了


是誤解,一般來說 P 是前提。所以基本是CA里選,不是任意3選2.

為什麼呢?

P 意指分區容忍性。 這個分區容忍性什麼意思,很多人容易望文生義,不要見風就是雨,理解成別的什麼意思。所謂分區指的是網路分區的意思,這個一樣還是容易望文生義。詳細一點解釋,比如你有A B兩台伺服器,它們之間是有通信的,突然,不知道為什麼,它們之間的網路鏈接斷掉了。好了,那麼現在本來AB在同一個網路現在發生了網路分區,變成了A所在的A網路和B所在的B網路。所謂的分區容忍性,就是說一個數據服務的多台伺服器在發生了上述情況的時候,依然能繼續提供服務。

所以顯而易見的,P是大前提,如果P發生了,咱們的數據服務直接不服務了,還談個毛的可用性和一致性呢。

因此CAP要解釋成,當P發生的時候,A和C只能而選一。

舉個簡單的例子,A伺服器B伺服器同步數據,現在A B之間網路斷掉了,那麼現在發來A一個寫入請求,但是B卻沒有相關的請求,顯然,如果A不寫,保持一致性,那麼我們就失去了A的服務,但是如果A寫了,跟B的數據就不一致了,我們自然就喪失了一致性。

這裡設計就涉及到架構師的選擇了。注意這裡的一致性是強一致性,意思是AB的數據時刻都是同步的,如果我們放棄了強一致性,不代表我們的數據就是一定是不一致的了,我們可以讓A先寫入本地,等到通信恢復了再同步給B,這就是所謂的最終一致性,長遠的看我們的數據還是一致的,我們只是在某一個時間窗口裡數據不一致罷了。如果這個時間窗口小過了用戶邏輯處理的時間。那麼其實對於用戶來說根本毛都感覺不到。

最終一致性有個很有意思的協議叫gossip就跟傳八卦一個意思,我就把我收到里信息里我本地沒有的部分加到我本地,再把這個信息發出去,那麼長遠的看,網路時好時壞,但是最終所有人都會有所有的信息。因此我們還是能夠保證數據的最終一致性的。

綜上,CAP應該描述成,當發生網路分區的時候,如果我們要繼續服務,那麼強一致性和可用性只能2選1。


可用性本身就是連續譜,99-99.9-99.99-99.999%。一致性也是,強一致性也即linearizability線性化,有界stale一致性,單調原子視圖一致性,前綴一致性,最終一致性,你說哪個是一致性?網路分區不可避免,但是幾率在不同場景不同,數據中心內幾率極小,且事實上我們無法分辨網路分區還是只是響應延遲放大。綜上所述,這是一個trade off,可以看daniel abadi文章


CAP中的C,跟ACID中的C,根本就不是一個東西。


是存在誤解。

我們先看看CAP的定義:

  1. C指的是atomic consistency,也就是linearizability,這是個比較嚴格的一致性定義
  2. A指的是availability,是說伺服器要在一定的時間內返回正確的答案
  3. P指的是伺服器之間無法通信。

因此CAP很好理解,伺服器節點之間無法通信,對於任意的請求你是沒辦法給出正確的回復的,因為伺服器不知道自己是不是最新的狀態。

但是在實際的系統實現中的要求沒有這麼極端,不是非黑即白的。

比如說availability,假設這個規定的時間是1秒,那我偶爾時間超過1秒才返回結果也不是不可接受的,只要這個次數不要超過一定的比例即可,因此實際的系統中通常說的availability通常指的是一個百分比,比如說99.99%。

再比如說partition,一個系統通常由多個節點組成,而且通常會放在不同的地方,比如說不同的機房或者rack,那這些所有的位置的通信全部中斷的可能性就很小。比如說一個raft group,只要大多數節點能互相通信這個系統就還是可用的,從而最大限度的降低partitition帶來的可用性的影響。

最後說consistency,linearizability是一個很強的一致性,但是不是所有的業務都需要這種特性,比如說緩存等。

因此CAP指出了分散式系統的上限,比如說無法在極端情況下達到100%的可用性,但是對實際的系統設計沒有太大的知道意義。


推薦閱讀:

zhh-2015在分散式系統和資料庫領域研究水平和工程能力怎樣?
大數據計算框架除了 MapReduce 還有哪些呢,不應該是 MapReduce 去解決所有問題吧?
到現在為止,NoSQL運動給資料庫系統留下什麼寶貴的思想?
為什麼很多分散式系統都是以DAG(Directed acyclic graph )實現運算的?
分散式系統工程如何搭建,有沒有一套完整的系統的實踐方法論,比如,存儲服務?

TAG:分散式系統 | 計算機科學 | 誤區 |