對于剛剛接觸分布式系統的小伙伴們來說,一提起分布式系統,就感覺高大上,深不可測。而且看了很多書和視頻還是一臉懵逼。這篇文章主要使用大白話的方式,帶你理解一下分布式系統中的CAP理論。保證你能聽懂。
1998年,加州大學的計算機科學家 Eric Brewer 提出,分布式系統有三個指標。
- Consistency
- AvAIlability
- Partition tolerance
它們的第一個字母分別是 C、A、P。
Eric Brewer 說,這三個指標不可能同時做到。這個結論就叫做 CAP 定理。
二、Partition tolerance
先看 Partition tolerance,中文叫做"分區容錯"。
大多數分布式系統都分布在多個子網絡。每個子網絡就叫做一個區(partition)。分區容錯的意思是,區間通信可能失敗。比如,一臺服務器放在中國,另一臺服務器放在美國,這就是兩個區,它們之間可能無法通信。
圖片
上圖中,G1 和 G2 是兩臺跨區的服務器。G1 向 G2 發送一條消息,G2 可能無法收到。系統設計的時候,必須考慮到這種情況。
一般來說,分區容錯無法避免,因此可以認為 CAP 的 P 總是成立。CAP 定理告訴我們,剩下的 C 和 A 無法同時做到。
三、Consistency
Consistency 中文叫做"一致性"。意思是,寫操作之后的讀操作,必須返回該值。舉例來說,某條記錄是 v0,用戶向 G1 發起一個寫操作,將其改為 v1。
接下來,用戶的讀操作就會得到 v1。這就叫一致性。
圖片
問題是,用戶有可能向 G2 發起讀操作,由于 G2 的值沒有發生變化,因此返回的是 v0。G1 和 G2 讀操作的結果不一致,這就不滿足一致性了。
為了讓 G2 也能變為 v1,就要在 G1 寫操作的時候,讓 G1 向 G2 發送一條消息,要求 G2 也改成 v1。
圖片
這樣的話,用戶向 G2 發起讀操作,也能得到 v1。
圖片
四、Availability
Availability 中文叫做"可用性",意思是只要收到用戶的請求,服務器就必須給出回應。
用戶可以選擇向 G1 或 G2 發起讀操作。不管是哪臺服務器,只要收到請求,就必須告訴用戶,到底是 v0 還是 v1,否則就不滿足可用性。
五、Consistency 和 Availability 的矛盾
一致性和可用性,為什么不可能同時成立?答案很簡單,因為可能通信失敗(即出現分區容錯)。
如果保證 G2 的一致性,那么 G1 必須在寫操作時,鎖定 G2 的讀操作和寫操作。只有數據同步后,才能重新開放讀寫。鎖定期間,G2 不能讀寫,沒有可用性不。
如果保證 G2 的可用性,那么勢必不能鎖定 G2,所以一致性不成立。
綜上所述,G2 無法同時做到一致性和可用性。系統設計時只能選擇一個目標。如果追求一致性,那么無法保證所有節點的可用性;如果追求所有節點的可用性,那就沒法做到一致性。
在什么場合,可用性高于一致性?
舉例來說,發布一張網頁到 CDN,多個服務器有這張網頁的副本。后來發現一個錯誤,需要更新網頁,這時只能每個服務器都更新一遍。
一般來說,網頁的更新不是特別強調一致性。短時期內,一些用戶拿到老版本,另一些用戶拿到新版本,問題不會特別大。當然,所有人最終都會看到新版本。所以,這個場合就是可用性高于一致性。
驗證CAP理論
系統總是會有錯誤,那我們就來看看可能會出現什么錯誤。
圖片
N1節點更新了V0到V1,想在也想把這個消息通過M操作告訴N1節點,卻發生了網絡故障。這時候小明和小華都要同時訪問這個數據,怎么辦呢?現在我們依然想要我們的系統具有CAP三個特性,我們分析一下會發生什么。
(1)系統網絡發生了故障,但是系統依然可以訪問,因此具有容錯性。
(2)小明在訪問節點N1的時候更改了V0到V1,想要小華訪問節點N2的V數據庫的時候是V1,因此需要等網絡故障恢復,將N2節點的數據庫進行更新才可以。
(3)在網絡故障恢復的這段時間內,想要系統滿足可用性,是不可能的。因為可用性要求隨時隨地訪問系統都是正確有效的。這就出現了矛盾。
正是這個矛盾所以CAP三個特性肯定不能同時滿足。既然不能滿足,那我們就進行取舍。
有兩種選擇:
(1)犧牲數據一致性,也就是小明看到的衣服數量是10,買了一件應該是9了。但是小華看到的依然是10。
(2)犧牲可用性,也就是小明看到的衣服數量是10,買了一件應該是9了。但是小華想要獲取的最新的數據的話,那就一直等待阻塞,一直到網絡故障恢復。
現在你可以看到了CAP三個特性肯定是不能同時滿足的,但是可以滿足其中兩個。
三、CAP特性的取舍
我們分析一下既然可以滿足兩個,那么舍棄哪一個比較好呢?
(1)滿足CA舍棄P,也就是滿足一致性和可用性,舍棄容錯性。但是這也就意味著你的系統不是分布式的了,因為涉及分布式的想法就是把功能分開,部署到不同的機器上。
(2)滿足CP舍棄A,也就是滿足一致性和容錯性,舍棄可用性。如果你的系統允許有段時間的訪問失效等問題,這個是可以滿足的。就好比多個人并發買票,后臺網絡出現故障,你買的時候系統就崩潰了。
(3)滿足AP舍棄C,也就是滿足可用性和容錯性,舍棄一致性。這也就是意味著你的系統在并發訪問的時候可能會出現數據不一致的情況。
實時證明,大多數都是犧牲了一致性。像12306還有淘寶網,就好比是你買火車票,本來你看到的是還有一張票,其實在這個時刻已經被買走了,你填好了信息準備買的時候發現系統提示你沒票了。這就是犧牲了一致性。
但是不是說犧牲一致性一定是最好的。就好比MySQL中的事務機制,張三給李四轉了100塊錢,這時候必須保證張三的賬戶上少了100,李四的賬戶多了100。因此需要數據的一致性,而且什么時候轉錢都可以,也需要可用性。但是可以轉錢失敗是可以允許的。