CAP理論中的P到底是個什麼意思?

在CAP理論中,C代表一致性,A代表可用性(在一定時間內,用戶的請求都會得到應答),P代表分區容錯。

這裡分區容錯到底是指數據上的多個備份還是說其它的 ? 我感覺分散式系統中,CAP理論應該是C和A存在不可同時滿足, 既要保證高可用,又要保證強一致性,因為多個節點之間存在數據複製,所以要麼保證強一致性,就不一定能在指定的時間內返回客戶的請求, 要麼保證高可用,但是各個節點的數據不一定是一致的。 但是和P有什麼關係呢 ?


一個分散式系統裡面,節點組成的網路本來應該是連通的。然而可能因為一些故障,使得有些節點之間不連通了,整個網路就分成了幾塊區域。數據就散布在了這些不連通的區域中。這就叫分區。

當你一個數據項只在一個節點中保存,那麼分區出現後,和這個節點不連通的部分就訪問不到這個數據了。這時分區就是無法容忍的。

提高分區容忍性的辦法就是一個數據項複製到多個節點上,那麼出現分區之後,這一數據項就可能分布到各個區里。容忍性就提高了。

然而,要把數據複製到多個節點,就會帶來一致性的問題,就是多個節點上面的數據可能是不一致的。要保證一致,每次寫操作就都要等待全部節點寫成功,而這等待又會帶來可用性的問題。

總的來說就是,數據存在的節點越多,分區容忍性越高,但要複製更新的數據就越多,一致性就越難保證。為了保證一致性,更新所有節點數據所需要的時間就越長,可用性就會降低。


分區指的是,你整個分散式系統不再是連通的。 比如節點分成了兩組,彼此之間無法通信。

這種情況,比其中一組全宕機更複雜。因為兩組都可能獨立對外提供服務。

但我們可以設想不提供P,也就是不允許出現分區的情況,是有可能同時提供AC兩個特性的。 實際上這在分散式系統中,並不受控。所以一般認為P是必須提供的,所以AC需要權衡。也就是題主的看法。


滿足P代表對失敗的容忍,滿足 A,C,而不滿足 P 意味著當網路分區沒有發生時,系統既能滿足 A,也能滿足C,而當存在網路分區時,將不再保證 A,C。實際上我們說一個分散式系統滿足可用性,通常也附帶了滿足一定程度的P,因為失敗一定存在,而不存在失敗滿足可用性又是如此容易;一致性也如此。

有一個等價的理論:在一個不可靠的分散式環境中中,無法同時滿足活性(A)和安全性(C)。這個理論把 不可靠作為理論所處的模型的性質,隱含了系統需要能容忍失敗。而 CAP 將P作為系統性質提出,隱含了分散式環境不可靠這一事實。


"Partition Tolerance" 這個形容詞確實挺容易 confuse 的,《A Critique of the CAP Theorem》文章曾這樣批評:

we can interpret partition tolerance as meaning 「a network partition is among the faults that are assumed to be possible in the system.」

It is misleading to say that an algorithm 「provides partition tolerance,」 and it is better to say that an algorithm 「assumes that partitions may occur.」

至於 Network Partition 應當理解為 CAP 理論中討論的故障模型,這裡需要注意 Network Partition 並非節點 Crash(節點 Crash 屬於 FLP 的故障模型),更側重於 "節點雙方一時聯繫不上對方" 的一個狀態。

造成 Partition 的原因可能是網路不可達,也可能是 GC 的 Stop The World 阻塞太久,也可能是 CPU 彪到一個死循環上,總之種種血案。aphyr 曾整理過這麼一批血案可以參考: aphyr/partitions-post


就是一個很混亂且缺乏解釋力的理論,那麼較勁幹啥。

理論的原意大概是說你不可能設計一個系統在保證出現一些網路交換器故障導致一些批網路節點無法和另一批節點通信的情況下P依然保證數據一致性C,且保證服務可用A。

這理論聽聽就行了。如果你是個這個領域的新人,學會大規模系統里需要考慮交換機和路由器壞掉的情況就可以了。


1,P是分散式系統的起點,全稱:network partition,常指拔網線和宕機,因為這兩種現象,同伴是無法區分的,所以歸為一類。分散式系統下,P是大概率事件,假設伺服器開一年必宕機一次,則365台的集群必然天天宕機。數據分存這365台之上,則數據必然天天不完整。你設計的分散式系統能容忍嗎?絕大多數是不能,不能則

2,複製,是解決這一問題的標準做法

3,複製,引發了C

4,C引發了A


C:集群中所有機器狀態是一致的。

A:客戶端訪問集群中任意一個節點,總能得到"處理成功"的結果

假設有五個節點:n1~n5 ,出現網路分區被分成兩組:[n1~n2]和[n3~n5],那麼當n1出來客戶端請求時(為了處理這種情況,也就是說"容忍網路分區",即支持 P):

1:如果要保證C(一致性),那麼它需要把消息複製到所有節點,但是網路分區導致無法成功複製到n3~n5,所以它只能返回"處理失敗"的結果給客戶端。(這時系統就處於不可用狀態,即喪失了A

2:如果要保證可用性A,那麼n1就只能把消息複製到n2,而不用複製到n3~n5(或者無視複製失敗/超時),但n3同時也可能在處理客戶端請求(譬如對同一個值進行修改),n3也為了保證A而做了同樣的處理。 那麼 [n1~n2]和[n3~n5]的狀態就不一致了,於是就喪失了 C

那麼如果不支持P(也就是不容忍網路分區),也就是說(很樂觀的認為)假設系統不會出現網路分區~


Raft

既然是分散式理論中的概念,那給題主一個Raft的演示吧,裡面涉及了網路分化份額問題


假設a b c d 四台機器兩兩互聯,某一時間發生網路分區導致a b可以互聯,c d可以互聯,但是這兩組之間無法通信,這就是傳說的P

事實上工程上很難明確區分機器宕機和網路分區,甚至Gc stop World 這幾種情況,畢竟只能通過time out 來做判斷,這是分散式系統面臨的問題之一。

以上個人見解,歡迎指正。


CAP原理是個混淆硬體和軟體的偽原理,詳見CAP原理的偽命題及其解決辦法


推薦閱讀:

拜占庭將軍問題確保系統正常為什麼需要2k+1個正常節點?
ETH CS Master(全獎) vs UPenn CIS PhD,如何選擇?
TiDB和CockroachDB同為Spanner/F1的開源實現,有哪些重大差異?
分散式資料庫中為什麼要使用 Vector Clock?
區塊鏈的原理是什麼?

TAG:分散式系統 | 分散式伺服器 | 分散式一致性 | 並發並行與分散式系統 |