02.29 分佈式系統之—CAP 定理

在互聯網時代,我們的運用都是分佈式系統,部署在 N 臺機器上。說到分佈式系統我們就不得不說分佈式系統的祖先——集中式系統。它和分佈式系統是兩個完全相反的兩個概念,集中式系統就是把所有的程序和功能都放到一臺主機上,從而對外提供服務。集中式系統的優點就是容易理解、維護方便,它的的弊端也很明顯,如果這個主機出故障了那麼整個系統就崩潰了。著名投資家巴菲特有個關於投資的名言:

不要把雞蛋放在一個籃子裡

對於我們的系統而言也是如此,我們不可能保證主機永遠不壞、也無法保證自己的程序永遠不會出 bug ,所以問題是無法避免的,我們只能把“雞蛋”分散到不同的“籃子”裡,降低系統出故障的風險,這就是我們為什麼需要分佈式系統的原因之一。使用分佈式系統的另一個理由就是擴展性,畢竟單臺主機都會有性能的極限,分佈式系統可以通過增加主機數量來實現橫向水平性能的擴展。接下來我們看看分佈式系統中的一個基本定理 —— CAP定理 。

什麼是 CAP 定理

CAP 定理 指出對於一個分佈式系統來說,不可能同時滿足以下三點:

  • 一致性(Consistency)
  • 可用性(Availability)
  • 分區容錯性(Partition tolerance)

定理看起來很簡單,但是 一致性 、 可用性 、 分區容錯性 究竟是代表什麼意思呢?理解定理的最簡單的方式就是想象一個有兩個節點分別處在不同的分區(PS:可以簡單的把分區理解為不同的子網絡)的分佈式系統。

場景假設

我們假定一個很簡單的分佈式系統,系統由兩個系統 S1 和 S2 組成。兩個系統上面有兩個相同的變量 K ,該變量在兩個系統對應的初始值為 V0 。系統 S1 和 S2 可以進行通信同時也對外提供服務。我們假定的分佈式系統如下所示:

分佈式系統之—CAP 定理

客戶端 client 可以向 S1 和 S2 任何一個系統發起讀和寫請求。當一個服務接收到發過來的請求後進行一些相關業務操作,然後返回給客戶端 client ,發起寫請求的過程如下圖所示:

分佈式系統之—CAP 定理

客戶端發起讀請求的過程如下所示:

分佈式系統之—CAP 定理

我們的分佈式系統模型建立好了,接下來我們通過這個模型來分析 CAP 定理 中的一致性、可用性和分區容錯性的具體含義。

一致性(Consistency)

一致性 要求在一個寫操作完成之後的任何讀操作都必須返回該值或者以後進行寫操作的結果。在滿足一致性的分佈式系統中,客戶端發起一個寫請求到分佈式系統的任何一個子系統中,然後再向該系統中任何一個子系統發起讀請求查詢該變量對應的值,都會返回上次更新的最新結果。客戶端向一個 不滿足一致性 的分佈式系統發起寫-讀請求的過程如下所示:

分佈式系統之—CAP 定理

當客戶端向系統 S1 發送寫請求(write V1),得到成功返回響應後,再向系統 S2 發送讀請求讀取該變量的值,系統 S2 還是返回舊值 V0 。另一方面,我們看看客戶端向一個滿足 一致性 的分佈式系統發起寫-讀請求的過程:

分佈式系統之—CAP 定理

在這個滿足一致性的系統中,在上述過程中系統 S1 在返回客戶端請求結果之前會先把最新值V1 發送到系統 S2 ,然後才返回客戶端的寫請求結果。因此,當客戶端再去請求系統 S2 的時候就會返回最新值 V1 。

可用性(Availability)

可用性 要求在分佈式系統中非故障節點收到的每一個請求都必須返回響應。在一個滿足 可用性 的分佈式系統中,如果客戶端向系統中任意一個節點發送請求並且服務器沒有崩潰的情況下,則該節點必須響應客戶端,不管是哪個節點,只要收到請求,就必須告訴用戶,到底是 V0 還是V1 ,否則就不滿足可用性,不允許服務器忽略客戶端的請求。

分區容錯性(Partition tolerance)

分區容錯表明當消息從一個節點向另一個節點發送消息的過程中,消息可能會丟失。以實際效果而言,分區相當於對通信的時限要求。系統如果不能在時限內達成數據一致性,就意味著發生了分區的情況,必須就當前操作在 一致性 和 可用性 之間做出選擇。如果所有消息都無法發送的話,分佈式系統的各個節點將無法同步消息。如下所示:

分佈式系統之—CAP 定理

一般來說,分區容錯無法避免,因此可以認為 CAP定理 的 分區容錯性 總是成立。 CAP 定理告訴我們,剩下的 一致性 和 可用性 無法同時做到。通常我們為了分區容錯,我們的系統必須保證能夠在任意網絡分區下正常運行。

為何不能同時滿足一致性和可用性

我們現在知道了 一致性 、 可用性 、 分區容錯性 所表示的具體含義,接下來看看為什麼在一個分佈式系統中不能同時滿足 一致性 和 可用性 。我們假定存在一個同時滿足這三個特性的系統。首先要做的就是對該系統進行分區,分區後系統如下所示:

分佈式系統之—CAP 定理

下一步,客戶端向分佈式系統的節點 S1 發送一個寫請求(write V1),系統只要是可用的,該節點總是會返回響應。但是系統存在網絡分區,因此節點 S1 無法將最新值 V1 通知節點 S2 去更新。如下所示:

分佈式系統之—CAP 定理

接下來,客戶端向分佈式系統的節點 S2 發送一個讀請求(read K)查詢變量 K 的值,同樣的,系統只要是可用的,該節點總是會返回響應,但是系統存在網絡分區,因此節點 S2 無法從節點 S1 獲取到最新值 V1 進行更新。如下所示:

分佈式系統之—CAP 定理

客戶端已經向節點 S1 發送寫請求(write V1)成功後,再向節點 S2 發起讀請求,得到的返回值是舊值 V0 。這和我們假設的一致性衝突。如果要保證節點 S1 的一致性,那麼節點 S1 必須在寫操作時,鎖定節點 S2 的讀操作和寫操作。只有當數據同步後,才能重新開放節點 S2 的讀寫操作。那麼在鎖定期間, S2 不能讀寫,它就沒有可用性了。再來看看,我們如果保證節點 S2 的可用性,那麼就不能鎖定節點 S2 的讀寫操作,所以一致性不成立。所以,節點 S2 無法同時做到一致性和可用性。系統設計時只能選擇一個目標。如果追求一致性,那麼無法保證所有節點的可用性,如果追求所有節點的可用性,那就沒法做到一致性了。

總結

CAP定理 指明瞭分佈式系統的三大指標 一致性(Consistency) 、 可用性(Availability) 和 分區容錯性(Partition tolerance) 不能同時滿足,該定理是分佈式系統的基本定理,也是理解分佈式系統的起點。(PS: 像我們常用的註冊中心 Eureka ,因為節點之間的狀態同步採用的異步方式,所以不能保證任意時刻各個節點間的狀態一定是一致的,只能保證節點間最終狀態是一致的。所以按照 CAP理論 , Eureka 的選擇就是放棄了 一致性 ,選擇 可用性 和分區容錯性 。)

來源:推酷 https://www.tuicool.com/articles/RfQZVfF


分享到:


相關文章: