天天看點

java cap理論_架構師都該懂的 CAP 定理

java cap理論_架構師都該懂的 CAP 定理

面對可能出現的網絡延遲,不可預估的請求流量等情況,設計一個分布式系統,我們通常圍繞系統高可用,資料一緻性的目标去規劃和實作,想要完全實作這個目标,卻并非易事。由此,分布式系統領域誕生了一個基本定理,即 CAP 定理,用于指導分布式系統的設計,從系統高可用,資料一緻性,網絡容錯三個角度将分布式系統的特性抽成一個分區容錯一緻性模型。這樣一來,讓系統設計者隻需根據業務場景特點,進行權衡設計适合業務場景的分區容錯一緻性模型即可,很大程度簡化了分布式系統設計的難度。

也是以,CAP 定理是架構師所必須要掌握的内容,它影響着架構師對分布式系統的技術選型,技術決策。既然如此重要,接下來,我們就一起學習下 CAP 定理吧。

什麼是 CAP

CAP 定理最初是由加州大學伯克利分校的計算機科學家埃裡克·布魯爾(Eric Brewer)在 2000 年的 ACM PODC 上提出的一個猜想,也是以被叫做布魯爾定理。後來在 2002 年,麻省理工學院的賽斯·吉爾伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)發表了 CAP 定理的證明,讓它成為分布式系統領域公認的一個定理。

CAP 定理指出了,在一個跨區域網絡連接配接,共享資料的分布式系統中,一緻性(Consistency),可用性(Availability)和分區容錯性(Partition Tolerance) 這三個限制屬性最終隻能同時滿足二個。

java cap理論_架構師都該懂的 CAP 定理

下面是關于這三個屬性的簡單描述:

一緻性:用戶端進行讀操作得到的資料永遠是最近一次寫入的資料,要求了對資料讀寫的強一緻性。

可用性:用戶端的請求在限定時間内總能從非故障的系統節點得到正常的響應,其中不能有逾時,不能出錯如 502之類。

分區容錯性:就是出現網絡分區現象,即節點間無法正常通信,資料同步出現延時等情況時,系統仍能繼續提供服務。

需要注意的是,CAP 描述了一個正常的分布式系統場景:有網絡連接配接,且資料跨節點進行共享。如果在整個系統中,資料隻有一份,并且其他節點沒有對應的副本,也不需要進行跨節點的資料共享,這樣分布式系統就不是 CAP 關心的對象了,也談不上結合 CAP 定理去設計和實施。

深入認識 CAP

了解 CAP 基本概念之後,我們再來分别對 C,A,P 三個屬性進一步學習下,加深對 CAP 的了解。

C:一緻性

這裡的一緻性從不同角度有着各自的描述方式,在分布式系統中表現是每個節點的資料是相同;而對于用戶端,表現是讀操作所得到的結果永遠是最新寫入的。其中需要明确的是,對于分布式系統節點來說,是可能出現某個時刻擁有不同的資料的情況:如果在某個節點執行原子性操作時,對于執行過程中的節點資料跟其他節點就并不完全一緻,隻有原子性操作執行完成後,節點的資料才會繼續保持同步。比如常見的事務操作,隻有事務送出後,用戶端才能讀取到事務寫入的資料,失敗則復原為舊的資料,不會出現讀取事務中間寫入資料的情況。

一緻性要求了在分布式環境下的操作要就像在單機上完成的一樣,當用戶端發起寫請求時,收到寫請求的節點會及時響應,并将更新的資料同步到另一個節點,保證資料一緻性。具體的工作流程,如下所示:

用戶端向節點 1 發送寫操作,将資料 X 更新為 1 ,

更新操作成功,系統将更新的資料從節點 1 同步到節點 2,将節點 2 的舊資料 X 也更新為 1。

用戶端再向節點 2 發送讀操作擷取資料 X 時,就會得到 X 最新的值:1。

java cap理論_架構師都該懂的 CAP 定理

一緻性強調了資料的強一緻,這一點要求對于一些系統可以說是十分重要的。比如電商系統的庫存扣減,金融系統的轉賬扣款等場景,任何出現一緻性的問題,都可能會造成很嚴重的後果。

A:可用性

介紹完一緻性,再來看下可用性,雖然可用性概念相對簡單,但重要程度跟一緻性一樣。要讓系統滿足可用性,就是要保證無論除了所有節點出現故障的情況外,系統都能傳回有效的響應,允許響應給用戶端是舊的資料,但不能出現響應失敗,逾時的情況。

可用性強調的是服務可用,但不保證資料的正确性。用一個簡單的例子來描述分布式系統的可用性如下:允許用戶端向節點 1 或者節點 2 發起讀操作,當其中某一個節點故障了,不管節點間資料是否一緻,隻要有節點服務能收到請求,就響應 X 的值,這樣就說明這兩個節點服務是滿足可用性。

java cap理論_架構師都該懂的 CAP 定理

在可用性的描述,還值得一提的是關于什麼算有效的響應。要傳回有效的響應,不能逾時,也不能出錯,結果不一定是正确的,比如傳回了舊資料,但是用戶端接收到後是能進行正常業務處理的。

P:分區容錯性

講完 C 和 A 之後,最後再講一下 P: 分區容錯性。由于分布式系統多個節點往往部署在多個網絡環境下進行互相通信,就難免出現一些網絡故障,如網絡丢包,網絡消息延遲,網絡中斷等情況,會導緻節點間的通信出現問題,資料同步操作無法完成,分區容錯性就要求了系統即使在網絡分區出現的情況下,能仍繼續對用戶端提供服務。

java cap理論_架構師都該懂的 CAP 定理

因為分布式系統與單機不同,它涉及到了多節點間的通信和資料互動,避免不了網絡問題,如果沒有分區容錯性,就意味着系統不允許出現節點間的通信出現任何錯誤,錯誤就意味着系統不可用,這在絕大數系統中無法接受的。是以對節點間的分區故障容錯是必須要考慮的,也是 CAP 定理中分區容錯性通常首先要保證的原因。

如何應用 CAP 定理

了解完 CAP 定理的一緻性(C),可用性(A)和分區容錯性(P)之後,我們再來看下如何使用這個定理。CAP 定理指明了 C,A,P三個屬性無法同時滿足,而在必有網絡互動和資料同步的情況下,就一定會有延遲和資料丢失的情況,對于這種情況我們又必須接受且保證系統不能挂掉。是以分區容錯性是必須要保證的,剩下的就是在一緻性 (C)和可用性(A)之間做選擇了。選擇了一緻性,保證資料正确性,但也意味系統可能存在不可用的情況;而選擇可用性,保證服務的高可用,但也意味資料可能出現不一緻性的情況。接下來就探讨下應用采用 CP 架構,AP 架構所各自的特點,以及如何根據不同的分布式場景選擇适合的架構政策。

CP

對于 CP 架構的分布式系統來說,為了保證一緻性,當出現網絡分區後,如果節點 1 上資料 X 已經更新為 2,但由于節點 間資料同步的通道已經中斷,節點 1 資料無法同步到節點 2,節點 2 上的資料 X 還是 1。此時如果用戶端通路節點 2 的資料 X,節點 2 就需要傳回錯誤,提示系統發生了錯誤,直到節點間的資料保持同步。當然這樣的處理方式明顯違背了可用性的要求,是以在 CAP 定理隻能滿足 CP。

java cap理論_架構師都該懂的 CAP 定理

如果一個分布式場景需要很強的一緻性,或者能容忍系統長時間無響應但是資料要保持一緻的情況,就比較适合使用 CP 架構設計對應的分布式系統。這樣的系統一旦發生網絡分區會導緻資料無法同步情況,就要犧牲系統的可用性,直到節點資料達到一緻後再響應。在開源社群中采用 CP 架構的應用不少,比如 Redis,HBase,MongoDB,ZooKeeper,Etcd,Consul 等都是放棄了一定可用性而選擇 CP 屬性。

AP

如果采用 AP 架構設計的分布式系統,為了保證可用性,當網絡分區發生後,同樣節點 1 上資料 X 已經更新為 2,但由于節點間資料同步的通道已經中斷,節點 1 資料無法同步到節點 2,節點 2 上的資料 X 還是 1。這是用戶端通路節點 2 擷取資料 X 時,收到是正常的響應,舊資料 X = 1,而實際上目前最新的資料 X 已經是 2 了,這裡就不滿足一緻性的要求了,是以在 CAP 定理隻能滿足 AP。

java cap理論_架構師都該懂的 CAP 定理

同樣适合 AP 的場景有很多,比如一些查詢系統,電商系統的商品查詢等,大多數為了保證系統的可用性,而犧牲一定的資料一緻性,這樣也保證了使用者體驗,在開源界中采用 AP 模型的典型應用有 Eurka,Cassandra。

必須三選二嗎

提到了 CAP 定理,大多數人都認為無論什麼情況,分布式系統隻能在 C 和 A 中選擇一個。但這裡的前提是系統發生了網絡分區情況,如果系統沒有發生網絡分區的情況,也就是說 P 不存在的時候,我們就沒有必要放棄 C 或者 A,是以進行架構設計時也應該考慮沒有分區情況下如何保證 CA。除此之外,一個分布式系統不一定隻能從 AP 與 CP 中做選擇,内部不同子產品所應對的場景也不同,完全有可能是一個子產品采用 AP 架構,另一個子產品采用 CP 架構。作為優秀的架構師,不應該受到大多數人對 CAP 定理所認識的局限,設計出符合自身業務場景的分布式系統才是重中之重。

總結

本文主要了解和認識 CAP 定理,以及每個 C,A,P 的含義,以及 CAP 定理的應用。掌握 CAP 定理,對架構師來說非常重要。因為對于分布式系統來說,網絡故障在所難免,如何在出現網絡故障的時候,維持系統按照正常的行為邏輯運作就顯得尤為重要。一個合格的架構師需要是能結合實際的業務場景和具體需求,基于 CAP 定理來進行權衡和設計可用且穩定的分布式系統。

參考資料

本文由部落格一文多發平台 OpenWrite 釋出!