不管你有沒有實戰(zhàn)過分布式系統(tǒng),赫赫有名的 CAP 定理一定有所耳聞,今天我們就來聊一聊 CAP 是什么?在分布式系統(tǒng)設計時,CAP 該如何選擇?
一、CAP 由來
CAP 定理:CAP Theorem,又被稱作布魯爾定理(Brewer's theorem),它是由加州大學伯克利分校教授埃里克·布魯爾(Eric Brewer)在 2000 年首次提出,主要是關于搜索引擎、分布式 Web 緩存權衡的一個猜想,直到 2002 年,麻省理工學院的賽斯·吉爾伯特(Seth Gilbert)和 南希·林奇(Nancy Lynch)才提出和發(fā)表對該猜想的正式證明,使之成為分布式計算領域公認的一個定理。
埃里克·布魯爾:
-
博士
-
加州大學伯克利分校教授
-
Inktomi 聯(lián)合創(chuàng)始人兼首席科學家
布埃里克·布魯爾 CAP 定理猜想
https://people.eecs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf
二、CAP 定義
如果你仔細研讀過埃里克·布魯爾 CAP 猜想原文,會發(fā)現(xiàn):在原文,作者并沒有詳細定義 Consistency、AvAIlability、Partition Tolerance 三個詞,因此,作為初學者甚至工作多年的小伙伴,因為學習 CAP 資料的不同,對 CAP 的理解也有所差別。
本文對 CAP 的定義基于 Seth Gilbert 和 Nancy Lynch 的 CAP 證明。
Seth Gilbert 和 Nancy Lynch 的 CAP 證明
https://groups.csail.mit.edu/tds/papers/Gilbert/Brewer6.pdf
C:Consistency,一致性
這里的一致性是指強一致性( Strong Consistency )或者線性一致性(Linearizable Consistency ),它要求多節(jié)點組成的分布式系統(tǒng),能夠像單節(jié)點一樣,如果一個寫操作返回成功,后面所有的讀請求都必須能讀到這個新數(shù)據,如果寫操作返回失敗,后面所有的讀操作都不能讀到這個數(shù)據。因此,CAP 中的一致性忽略了網絡延時,要求分布式系統(tǒng)節(jié)點數(shù)據的寫入能和單機一樣即時。
A:Availability,可用性
可用性要求系統(tǒng)提供的服務必須處于 100% 可用的狀態(tài),對于用戶的每一個操作請求,系統(tǒng)總能夠在有限的時間內返回結果。這里強調的可用性是完全可用,不允許任何不可用的情況出現(xiàn),因此這是一個非常理想的模型。
目前業(yè)內的分布式系統(tǒng)根本達不到 100% 的可用性,常見的可用性有:99.99% (俗稱 4 個 9),即一年內服務不可用時長有 50 分鐘;99.999%(俗稱 5 個 9),即一年內服務不可用時長只有 5 分鐘,99.9999%(俗稱 6 個 9),即一年內服務不可用時長只有 31秒。
P:Partition tolerance,分區(qū)容錯性
分區(qū)指的是在整個分布式系統(tǒng)中,因為各種網絡原因,導致系統(tǒng)被分隔成多個獨立的部分,它不僅包含通常意義上的網絡分區(qū),也包含因網絡丟包導致網絡不通的情況。因此,分區(qū)容錯是指當出現(xiàn)網絡分區(qū)后,系統(tǒng)能夠繼續(xù)“履行職責”。
如下圖:因為網絡分區(qū),ATM1 成了一個獨立的區(qū)域,ATM2 和 ATM3 又成了另外一個區(qū)域。
三、CAP 組合
按照 CAP 定理,三個要素中只能取兩個,組合如下圖:
CA - Consistency/Availability
如下圖:賬戶原余額是 0,在網絡狀況 ok 時,從 ATM1 存入 $100 ,再從 ATM2 查詢余額也是 $100。所以,可以滿足 CA。
但是,作為一名程序員,應該很清楚:日常開發(fā)中,很多工作都是為了彌補網絡異常導致的問題。因此在真實的分布式環(huán)境中,網絡狀況是一個不確定因素,假如忽略網絡狀況(即忽略 P),只考慮 CA 會出現(xiàn)什么情況?
如下圖:賬戶原余額是 0,當 ATM1 存入 $100 成功后, ATM1 和 ATM2 發(fā)生網絡分區(qū),為了保證兩個 ATM 數(shù)據的 C(一致性),ATM 2 需要禁止存款,查詢余額等操作,這樣 ATM2就不能工作了,和 A(可用性) 沖突;
如下圖:當 ATM1 存入 $100 成功后, ATM1和 ATM2 發(fā)生網絡分區(qū),為了保證兩個 ATM 系統(tǒng)的 A(可用性),ATM2 就必須提供存款,查詢余額等操作,但是 ATM1 存入 $100 的信息還未同步給 ATM2,所以,ATM2查詢到的賬戶余額是 0,余額不足,和 C(一致性) 沖突;
因此,分布式系統(tǒng),理論上是不能選擇 CA 架構。
CP - Consistency/Partition tolerance
如下圖:賬戶原余額是 0,當從 ATM1 存入 $100 時發(fā)生了網絡分區(qū),ATM1 和 ATM2 無法通信,因此,從 ATM1 上存入 $100 的信息無法同步給 ATM2,ATM2 為了保證和 ATM1 數(shù)據的一致性,需要拒絕存款或者查詢余額等操作,返回 error,這樣就犧牲了ATM2 的 A(可用性)。
AP - Availability/Partition tolerance
如下圖,賬戶原余額是 0,當從 ATM1 存入 $100 時發(fā)生了網絡分區(qū),ATM1 和 ATM2 無法通信,為了保證可用性,ATM 2 必須提供存款,查詢余額等操作。注意:盡管 ATM2提供了服務,但是它提供的數(shù)據可能是一個錯誤的,因此犧牲了 C(一致性)。
上文我們用實例分別描述了 CA,CP,AP,因為現(xiàn)實環(huán)境中,網絡的因素是不可控的,所以在大部分情況下,系統(tǒng)設計都會保留 P 屬性,而在 C 和 A 中二選一。但是,在分布式系統(tǒng)的設計中,真的只能三選二嗎?
四、CAP 誤區(qū)
誤區(qū)一:三選二有誤導性
這里是一個很容易產生誤解的地方,很多資料都強調 CAP 只能選擇 CP 或者 AP,但是在計算機的世界,并不是非黑即白。
CAP 定理闡明分布式系統(tǒng)只能選擇 CP 或 AP,但這里有一個隱藏的前提:那就是系統(tǒng)發(fā)生了“分區(qū)”。由于分區(qū)很少發(fā)生,如果系統(tǒng)不存在分區(qū)的情況下沒有理由犧牲 C 或 A ,CAP 在大多數(shù)時候允許完美的 C 和 A。因此,在架構設計時,既要考慮分區(qū)發(fā)生時選擇 CP 還是 AP,也要考慮沒有網絡分區(qū)時如何保證 CA。
誤區(qū)二:犧牲不等于什么都不做
CAP 定理闡明三個元素只能取兩個,需要“犧牲”(sacrificed)另外一個,這里的“犧牲”只是說在分區(qū)時無法同時保證 CA,并不是什么都不做。比如:上文提到的 99.99%、99.999% 或 99.9999% 系統(tǒng),一年內不可用時長不超過 1小時,因此可以在分區(qū)期間犧牲 C 或 A,在分區(qū)故障解決后,系統(tǒng)又重新恢復到 CA 狀態(tài)。
誤區(qū)三:CAP 忽略了網絡延時
CAP 定理的強一致性,要求分布式系統(tǒng)和單點系統(tǒng)一樣保證數(shù)據寫入的即時性,忽略了節(jié)點間數(shù)據復制有網絡延時(也就是說,當有數(shù)據寫入時,數(shù)據能夠瞬間復制到所有節(jié)點)。實際情況下,數(shù)據從節(jié)點 A 復制到節(jié)點 B,需要花費一定的時間。這就意味著,CAP 理論中的 C 在實踐中是不可能完美實現(xiàn)的,在數(shù)據復制的過程中,節(jié)點 A 和節(jié)點 B 的數(shù)據并不一致。
通過分析幾個誤區(qū),我們來回答文章標題:CAP 只能 三選二嗎?
CAP 中闡述只能選擇 CP 或者 AP,前提是系統(tǒng)出現(xiàn)了分區(qū),存在誤導性,因為分區(qū)比較少發(fā)生,因此在網絡狀況良好的,CAP都是可以保證的,在架構設計時,既要考慮分區(qū)發(fā)生時選擇 CP 還是 AP,也要考慮沒有網絡分區(qū)時如何保證 CA。
五、ACID 和 BASE
分析完 CAP 之后,就不得不提和 CAP 有千絲萬縷關系的 ACID 和 BASE。
ACID 是數(shù)據庫的傳統(tǒng)設計思路,CAP 與 ACID 容易產生誤解的一個原因是 ACID 和 CAP有相同的 C、A 字母,但是它們所代表的概念卻不同。
A:ACID 中的 A 是 Atomicity,原子性。一個事務中的所有操作,要么全部完成,要么全部失敗。CAP 中的 A 是可用性。
C:ACID 中的 C 是 Consistency,一致性。指事務不能破壞任何數(shù)據庫規(guī)則,如鍵的唯一性。與之相比,CAP 的 C 僅指單一副本這個意義上的一致性,因此只是 ACID 一致性約束的一個嚴格的子集。
I:Isolation,隔離性。正在處理但尚未提交的事務必須與任何其他事務保持隔離。事務隔離分為:讀未提交(Read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(Serializable)。隔離是 CAP 定理的核心:如果系統(tǒng)要求 ACID 隔離性,那么它在分區(qū)期間最多可以在分區(qū)一側維持操作。事務的可串行性(serializability)要求全局的通信,因此在分區(qū)的情況下不能成立。只要在分區(qū)恢復時進行補償,在分區(qū)前后保持一個較弱的正確性定義是可行的。
D:Durability,持久性。事務對數(shù)據的修改就是永久的,即便系統(tǒng)故障也不會丟失數(shù)據。
BASE,它是 “Basically Available, Soft state, Eventually consistent(基本可用、軟狀態(tài)、最終一致性)”的首字母縮寫。其中的軟狀態(tài)和最終一致性這兩種技巧擅于對付存在分區(qū)的場合,提高了可用性。BASE 中的最終一致性其實是對 CAP 強一致性的一個補充。
六、真實案例
CP 系統(tǒng)
redis、google BigTable、Hbase、MongoDB、 MemCacheDB
AP 系統(tǒng)
亞馬遜的 DynamoDB、以及衍生物 Apache Cassandra 和 Voldemort
CA 系統(tǒng)
Apache Kafka 是一個比較典型的 CA系統(tǒng)
Kafka 從 0.8 版本之后,引入了 Replication 副本的概念。通過 In-sync-replica(同步數(shù)據副本)機制,所有的數(shù)據寫入都必須在這個領導者節(jié)點中記錄。另外,通過將數(shù)據復制到不同的節(jié)點上,從而增強了數(shù)據在系統(tǒng)中的持久性(Durability)和可用(Availability)。在 Kafka Replication 的系統(tǒng)設計中,所有的數(shù)據日志存儲是設計在同一個數(shù)據中心(Data Center)里面的,也就是說,在同一個數(shù)據中心里網絡分區(qū)出現(xiàn)的可能性是十分之小的。
七、總結
CAP 是作者埃里克·布魯爾 的猜想,經過麻省理工學院 賽斯·吉爾伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)的證明。CAP 定理是分布式的一個基礎理論,它可以開闊設計師的思路,在多樣化的取舍方案下設計出多樣化的系統(tǒng)。
CAP 定理強調的是強一致性和 100% 服務可用,但是,在真實分布式環(huán)境中 100% 可用只能是一種理想的狀態(tài)。因此,4個9、5個9、6個9 的系統(tǒng), 哪怕它不符合 CAP 定理的可用性,也符合工作中對可用性的要求。CAP 的強一致性,在分布式環(huán)境的多個節(jié)點間,因為數(shù)據同步有網絡延時,因此也會存在一段時間的不一致。
CAP 定理斷言任何基于網絡的數(shù)據共享系統(tǒng),最多只能滿足數(shù)據一致性、可用性、分區(qū)容忍性三要素中的兩個要素。但是通過顯式處理分區(qū)情形,系統(tǒng)設計師可以做到優(yōu)化數(shù)據一致性和可用性,進而取得三者之間的平衡。
百種業(yè)務百種架構,在架構設計時,既要考慮分區(qū)發(fā)生時選擇 CP 還是 AP,也要考慮沒有網絡分區(qū)時如何保證 CA。