專注於Java領域優質技術號,歡迎關注
來自:小旋鋒
CAP定理是分佈系統中的一個基本定理,它指出任何分佈系統最多可以具有以下三個屬性中的兩個。
- 一致性 (Consistency)
- 可用性 (Availability)
- 分區容錯性 (Partition tolerance)
本文將以圖解的形式簡明地對 Gilbert and Lynch's specification and proof of the CAP Theorem (CAP定理的規範和證明) 進行概括總結
什麼是 CAP 定理?
CAP定理指出分佈式系統不可能同時具有一致性、可用性和分區容錯性。聽起來很簡單,但一致性、可用性、分區容錯性到底是什麼意思呢?確切地來說分佈式系統又意味著什麼呢?
在本文中,我們將介紹一個簡單的分佈式系統,並對分佈式系統的可用性、一致性和分區容錯性進行詮釋。有關分佈式系統和這三個屬性的正式描述,請參閱 Gilbert 和 Lynch 的論文。
分佈式系統
讓我們來考慮一個非常簡單的分佈式系統,它由兩臺服務器G1和G2組成;這兩臺服務器都存儲了同一個變量v,v的初始值為v0;G1和G2互相之間能夠通信,並且也能與外部的客戶端通信;我們的分佈式系統的架構圖如下圖所示:
一個簡單的分佈式系統
客戶端可以向任何服務器發出讀寫請求。服務器當接收到請求之後,將根據請求執行一些計算,然後把請求結果返回給客戶端。譬如,下圖是一個寫請求的例子:
客戶端發起寫請求
接著,下圖是一個讀請求的例子
客戶端發起讀請求
現在我們的分佈式系統建立起來了,下面我們就來回顧一下分佈式系統的可用性、一致性以及分區容錯性的含義。
一致性 (Consistency)
Gilbert 和 Lynch 在論文中的描述是:
any read operation that begins after a write operation completes must return that value, or the result of a later write operation也就是說,在一個一致性的系統中,客戶端向任何服務器發起一個寫請求,將一個值寫入服務器並得到響應,那麼之後向任何服務器發起讀請求,都必須讀取到這個值(或者更加新的值)。
下圖是一個不一致的分佈式系統的例子:
不一致的分佈式系統
客戶端向G1發起寫請求,將v的值更新為v1且得到G1的確認響應;當向G2發起讀v的請求時,讀取到的卻是舊的值v0,與期待的v1不一致。
下圖一致的分佈式系統的例子:
一致的分佈式系統
在這個系統中,G1在將確認響應返回給客戶端之前,會先把v的新值複製給G2,這樣,當客戶端從G2讀取v的值時就能讀取到最新的值v1
可用性 (Availability)
Gilbert 和 Lynch 在論文中的描述是:
every request received by a non-failing node in the system must result in a response也就是說,在一個可用的分佈式系統中,客戶端向其中一個服務器發起一個請求且該服務器未崩潰,那麼這個服務器最終必須響應客戶端的請求。
分區容錯性 (Partition tolerance)
Gilbert 和 Lynch 在論文中的描述是:
the network will be allowed to lose arbitrarily many messages sent from one node to another也就是說服務器G1和G2之間互相發送的任意消息都可能丟失。如果所有的消息都丟失了,那麼我們的系統就變成了下圖這樣:
網絡分區
為了滿足分區容錯性,我們的系統在任意的網絡分區情況下都必須正常的工作。
CAP定理的證明
現在我們已經瞭解了一致性、可用性和分區容錯性的概念,我們可以來證明一個系統不能同時滿足這三種屬性了。
假設存在一個同時滿足這三個屬性的系統,我們第一件要做的就是讓系統發生網絡分區,就像下圖的情況一樣:
網絡分區
客戶端向G1發起寫請求,將v的值更新為v1,因為系統是可用的,所以G1必須響應客戶端的請求,但是由於網絡是分區的,G1無法將其數據複製到G2
由於網絡分區導致不一致
接著,客戶端向G2發起讀v的請求,再一次因為系統是可用的,所以G2必須響應客戶端的請求,又由於網絡是分區的,G2無法從G1更新v的值,所以G2返回給客戶端的是舊的值v0
由於網絡分區導致不一致
客戶端發起寫請求將G1上v的值修改為v1之後,從G2上讀取到的值仍然是v0,這違背了一致性。
總結
我們假設了存在一個滿足一致性、可用性、分區容錯性的分佈式系統,但是我們展示了在一些情況下,系統表現出不一致的行為,因此證明不存在這樣一個系統
對於一個分佈式系統來說,P 是一個基本要求,CAP 三者中,只能根據系統要求在 C 和 A 兩者之間做權衡,並且要想盡辦法提升 P
閱讀更多 Java技術架構 的文章