分散式系統CAP定理教程

banq發表於2024-04-10

本文探討了 CAP 定理。理解 CAP 對於設計分散式系統至關重要,我們將深入研究每個屬性的含義。

什麼是分散式系統?
分散式系統將計算和資料分佈在網路內的多個互連節點上。這可能涉及解除安裝處理能力或在地理上分散資料以加快交付速度。與將資料儲存在單個位置的集中式系統不同,分散式系統將資料分佈在多個互連點上。

分散式系統的問題挑戰:
1、分割槽:
第一個問題是網路故障:網路連結可能會中斷,從而產生網路分割槽,從而使整個網路被分成孤立的組。每個分割槽都失去了與其他分割槽的通訊。系統承受此類分割槽的能力稱為分割槽容錯性。需要注意的是,實現 100% 分割槽容錯實際上是不可能的;所有分散式系統在某些時候都容易受到網路分割槽的影響。

這些分割槽雖然是暫時的,但會破壞系統各部分之間的通訊。讓我們考慮一下 Instagram 或 Facebook 等社交媒體平臺。如果發生分割槽,則在網路恢復之前,其他分割槽中的使用者可能無法看到新發布的照片​​。

2、一致性:
這引出了分散式系統的另一個重要屬性。 “一致性”。您已經注意到,如果發生兩個分割槽,則兩個分割槽看到的資料是不同的(或者換句話說,不一致)。一致性是衡量給定時間網路上的系統資料是否正確的指標。

一致性在金融應用中起著至關重要的作用。與社交媒體帖子不同,資料在整個系統中保持一致的速度是衡量系統一致性的指標。否則,這可能會導致嚴重的問題,例如雙重支出問題。

假設 Alice 的賬戶中有 100 美元,所有伺服器都與 Alice 的賬戶餘額 100 美元一致。Alice 從伺服器 A 處線上購買了價值 90 美元的手錶。伺服器 A 完成交易並向其他伺服器傳送通知,要求扣除 Alice 賬戶中的 90 美元。但在資訊傳播之前,突然發生了分割槽,伺服器 B 沒有收到 Alice 的交易。如果愛麗絲呼叫伺服器 B 並再次進行交易,伺服器仍然認為愛麗絲有 100 美元,並讓她再次消費。如果愛麗絲用 50 美元從伺服器 B 處買了一個包,交易仍然透過。
(這個案例其實是一個業務場景,技術試圖用一種通用方式解決業務。)

可以看出,在這種金融系統中,一致性是一個大問題,它應該具有更高的一致性。與社交媒體平臺相比,你以多快的速度收到朋友的更新並不重要。現在,我們知道金融交易系統需要更高的一致性。但我們該如何實現呢?

一致性級別可以有很多種,但讓我們來分析一下主要用於分散式系統的以下級別:

  • 線性化
  • 順序一致性
  • 因果一致性
  • 最終一致性

線性化Linearizability
線性化是最高的一致性級別。這種一致性演算法的工作原理是,如果有任何節點資料需要更新,就為系統中的所有節點新增一個讀取鎖。透過為所有節點新增讀鎖,我們可以確保系統中的任何節點都不會讀取部分更新的資料。一旦所有資料處於一致狀態,讀鎖就會被移除。如果存在網路分割槽,系統需要更多時間才能達到一致狀態。如果客戶端連線到一個節點,並在該節點被鎖定時請求讀取資料,會發生什麼情況呢?客戶端必須等待節點釋放鎖。

這就引出了第三個重要屬性--可用性。可用性是指當客戶端向節點提出請求時,節點會做出響應的屬性。如果節點沒有準備好為請求提供服務,客戶端將得不到響應或響應失敗。線上性化示例中,我們鎖定了節點,這樣客戶端就得不到響應。這意味著,在資料變得一致之前,節點是不可用的。我們可以得出這樣的結論:如果一致性越高,我們就無法實現更高的可用性。

順序一致性
與線性化相比,順序一致性是一種寬鬆的一致性模型。順序一致性不是為所有資料更新鎖定所有節點,而是按時間順序鎖定節點。想想聊天應用程式。當兩個人聊天時,兩個人的資訊都應該按照正確的時間順序排列。否則,理解起來就會一團糟。讓我們透過一個例子來理解。

Alice 需要向聊天群組傳送一條資訊,她向系統傳送了這條資訊。假設系統沒有分割槽,她的資訊會傳播到所有節點。現在,Bob 也需要向群組傳送一條資訊,但由於發生了網路分割槽,一些節點沒有更新 Bob 的資訊。現在,如果愛麗絲在這個分割槽系統中傳送另一條資訊,一些節點仍然不會更新鮑勃的資訊。如果節點不更新鮑勃的資訊,只新增愛麗絲的資訊,聊天就會變得一團糟。在這種情況下,順序一致系統會在節點上加一個寫鎖,只有在所有之前釋出的資料都已新增的情況下,系統才能寫入節點。在節點更新以前的資料之前,它必須等待以前傳送的資訊到達節點。

在這種一致性模式下,我們只考慮每個節點資料的順序一致性。與線性化模式相比,線上性化模式中,寫鎖會一直應用到事件的順序解決為止,而在這種模式中,節點是可用的。客戶端仍然可以從分割槽系統中的給定節點獲得響應,但最多隻能獲得順序正確的最後一個資料。

因果一致性
因果一致性是一種更為寬鬆的一致性模型,它不考慮順序。因果一致性只考慮資料之間的關係。例如,想想一個社交媒體平臺,你可以在上面釋出圖片和評論。愛麗絲在平臺上釋出了一張照片,與此同時,鮑勃也在平臺上釋出了一張照片。這兩個帖子沒有任何關係。釋出的先後順序不會影響第三人查理檢視這兩張照片。但是,每張照片都有一個評論區。當查理看到照片上的評論時,這些評論應按時間順序排列,以便他理解。這個系統中的評論是因果一致的。這意味著,在某些情況下,順序確實很重要,但並非在所有情況下都如此。如果存在不相關的實體(如帖子),則一致性更寬鬆,而評論則依賴於相關的帖子。

最終一致性
現在,我們可以輕鬆理解 "最終一致性 "了。想想看,同樣是一個沒有評論功能的社交媒體平臺。現在,愛麗絲和鮑勃發布了照片,查理可以在自己的 feed 上看到他們釋出的照片。他收到資料的順序並不重要。

這讓我們想到關於可用性的另一個重要事實。線上性化一致性級別中,由於鎖定,我們無法實現更高的可用性。但在最終一致性中,我們不需要任何鎖。因此,伺服器節點在任何時候都是可用的。

什麼是 CAP 定理?
現在,我們發現了 CAP 定理的全部內容,是時候完成拼圖了。我們已經討論了分散式系統的三個特性。分割槽容忍性(Partition Tolerance)告訴我們系統可以容忍分割槽;一致性(Consistency)確保資料在分散式系統中保持一致;可用性(Availability)確保系統始終響應客戶請求。CAP 定理指出,我們只能從三個屬性中選擇兩個。讓我們來看看這三種情況。

1、選擇分割槽容錯性和一致性而非可用性
在這種情況下,我們允許系統有分割槽。但我們需要保持系統的一致性。我們討論過的金融交易場景就屬於這種情況。為了保持一致性,我們必須鎖定節點,直到資料在系統中變得一致。只有這樣,才允許從系統中讀取資料。因此,可用性是有限的。

2、選擇分割槽容忍度和可用性而非一致性
在這種情況下,我們不需要系統具有嚴格的一致性。回顧一下最終一致性中討論的社交媒體系統。我們不需要一致的資料,而是需要資料以任何順序排列。有了寬鬆的一致性級別,我們就不需要鎖定節點,而且節點總是可用的。

3、分割槽容差下的可用性和一致性
這種系統更像是集中式系統,而不是分散式系統。如果沒有網路分割槽,我們就無法構建系統。如果我們同時確保可用性和一致性,那麼就不可能存在任何分割槽。也就是說,這是一個集中式系統。因此,我們不討論分散式系統中的可用性和一致性系統。

CAP 定理用例
現在你知道什麼是 CAP 定理了吧。讓我們來看看上述三種情況下使用的一些工具示例。

1、分割槽容忍和一致性系統
Redis 和 MongoDB 是針對 CP(一致和分割槽容忍系統)的流行資料庫解決方案。這些資料庫可作為分散式資料庫執行,並允許存在分割槽。即使存在分割槽,也能讓您在連線的所有資料庫中獲得一致的資料。

2、分割槽容忍度和可用系統
該系統不太關心繫統的一致性。它關心的是響應速度和執行速度。這包括 Cassandra 和 CouchDB 等資料庫。這些資料庫專為在分散式環境中執行和加快執行速度而構建。

3、一致可用的系統
這類系統不是分散式系統,而是集中式系統。SQLite 和 H2 等資料庫可在單個節點上執行。這些資料庫無需鎖定節點,而且是唯一的節點,因此始終保持一致性和可用性。但在分散式系統上卻不能使用,因為它不能容忍分割槽。


為什麼 MYSQL 沒有被列入其中?
一般認為,MySQL 是一種 CA 系統,旨在提供良好的一致性和可用性,同時犧牲分割槽容錯性。原因在於 MYSQL 以主-從模式執行,其中主節點是客戶端要訪問的節點。因此,我們所說的並不是真正的分散式系統。但透過不同的配置,你仍然可以把它當作一個 CP 系統來使用。

如你所見,CAP 定理對分散式系統施加了限制。作為系統設計者和開發者,我們必須選擇優先考慮的屬性:一致性、可用性或分割槽容忍性。所選擇的一致性模型將決定我們是優先考慮高可用性,還是犧牲一些可用性來確保一致性。有許多工具可以幫助你根據這些權衡來設計應用程式。明智選擇!下次遇到分散式系統時,請考慮這三個關鍵特性。

相關文章