讓我們一起聊聊對CAP理論的理解
介紹
最近經(jīng)??吹接腥税l(fā)一個Go實(shí)現(xiàn)的分布式事務(wù)管理器dtm,看到star增的挺猛的,索性看看代碼實(shí)現(xiàn),畢竟工作中部分場景也用的上。
在寫源碼分析之前,我們先來簡單入門一下分布式理論。
CAP
分布式系統(tǒng)中很大的一個難點(diǎn)在于各個節(jié)點(diǎn)之間的狀態(tài)如何同步,CAP就是分布式系統(tǒng)領(lǐng)域一條已經(jīng)被證明的定律。
其中各個字母的含義如下:
- Consistency(一致性)
- Availability(可用性)
- Partition tolerance(分區(qū)容忍性)
我們先用一個簡單的例子來說明。
假設(shè)我們的系統(tǒng)是由兩個服務(wù)組成的:G1和G2。
G1和G2維護(hù)了同一條記錄V0。外部客戶端(Client)可以調(diào)用任意一個服務(wù)。
當(dāng)一個客戶端對任意一個服務(wù)發(fā)起讀|寫請求,那么被請求的那個服務(wù)器根據(jù)客戶端的請求,處理、響應(yīng)結(jié)果。
比如客戶端向G1發(fā)起一個讀操作,客戶端G1響應(yīng)請求。
又比如客戶端向G1發(fā)起一個寫操作,把V0修改成V1。
到這里,我們建立了這樣一個系統(tǒng)。接下來看看系統(tǒng)的一致性、可用性和分區(qū)容忍性意味著什么。
Consistency(一致性)
這個一致性和事務(wù)中ACID中的C還是有區(qū)別的。事務(wù)中的C更多是指在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這里的完整性包括一些外鍵約束、鍵的唯一性等。
而分布式事務(wù)中的C指的是,寫操作之后的讀操作,必須返回該值,這就等同于所有節(jié)點(diǎn)訪問的是同一份最新數(shù)據(jù)的副本。
下面是一個非一致性的例子。
客戶端成功請求G1服務(wù)器寫V1。假設(shè)當(dāng)前服務(wù)G1和G2不能互通(網(wǎng)絡(luò)分區(qū)),導(dǎo)致G1數(shù)據(jù)不能同步到G2,此時客戶端從G2讀取數(shù)據(jù),依舊返回V0。
來看一個滿足一致性的例子。
在這個系統(tǒng)中,G1收到客戶端寫V1的操作,G1在修改自身數(shù)據(jù)的同時,會把V1數(shù)據(jù)同步到G2。G1在收到G2的響應(yīng)后,才向客戶端響應(yīng)結(jié)果。這樣,之后無論客戶端從哪個節(jié)點(diǎn)讀取數(shù)據(jù),都能獲取到V1值。
Availability(可用性)
可用性指的是系統(tǒng)中非故障節(jié)點(diǎn)接收到的每一個請求都必須響應(yīng)。
在一個可用的系統(tǒng)中,如果客戶端向服務(wù)器發(fā)送一個請求,那么服務(wù)器必須響應(yīng)客戶端每一個請求,不允許忽略客戶端請求。
Partition Tolerance(分區(qū)容忍性)
什么分區(qū)?
網(wǎng)絡(luò)分區(qū)。
網(wǎng)絡(luò)分區(qū)咋么理解?
假設(shè)有兩臺服務(wù)器A和B,本來他們兩是正常通信的,不知道啥原因,他們之間的網(wǎng)絡(luò)鏈接斷開,導(dǎo)致無法正常通信。此時本來在同一個網(wǎng)絡(luò)的AB,發(fā)生了網(wǎng)絡(luò)分區(qū)。變成了A所在的A網(wǎng)絡(luò)和B所在的B網(wǎng)絡(luò)。這就是網(wǎng)絡(luò)分區(qū)。
容忍性是指什么?
當(dāng)一個服務(wù)的多臺服務(wù)器發(fā)生上述網(wǎng)絡(luò)分區(qū)的時候,系統(tǒng)依舊能正常提供服務(wù)。
對CAP的誤解
網(wǎng)上很多文章都是這么說的:
一個分布式系統(tǒng)最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯性(Partition tolerance)這三項(xiàng)中的兩項(xiàng),這被稱為CAP定律。
似乎CAP被解釋成一種三選二的定律。
看到一篇文章CAP Twelve Years Later: How the "Rules" Have Changed[1]有一段CAP的完整表述:
The CAP theorem asserts that any net-worked shared-data system can have only two of three desirable properties。
按照表述,發(fā)現(xiàn)網(wǎng)上這句話存在一定的誤導(dǎo)性。
CAP定律的前提是P(網(wǎng)絡(luò)分區(qū))發(fā)生后,才會有CA的選擇。
當(dāng)P發(fā)生的時候,而我們的系統(tǒng)直接不服務(wù)了,那就不存在選擇什么CA了。
因此CAP的正常理解應(yīng)該是:當(dāng)P(網(wǎng)絡(luò)分區(qū))發(fā)生的時候,如果我們要繼續(xù)提供服務(wù),那么C(一致性)和A(可用性)只能2選1了。
Consistency和Availability的矛盾
為什么當(dāng)P發(fā)生時,CA只能二選一?
還是之前那個簡單的例子。
假設(shè)此時G1和G2發(fā)生了網(wǎng)絡(luò)分區(qū)。
接下來我們的客戶端請求G1寫V1數(shù)據(jù)。由于分區(qū),G1不能同步數(shù)據(jù)到G2。
如果我們保證G2的可用性,那么當(dāng)客戶端請求G2數(shù)據(jù)的時候,G2能正常響應(yīng)V0數(shù)據(jù),但是數(shù)據(jù)和G1不一致,無法保證一致性。
如果我們保證G2的一致性,那么在G1寫操作的時候,就必須鎖定G2的讀寫操作,那么此時G2就處于不可用狀態(tài),無法保證其可用性。
因此,Consistency和Availability存在矛盾。
參考
https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/
https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/
https://www.zhihu.com/question/64778723