2021-2-22:請你說下 CAP 理論並舉例

乾貨滿滿張雜湊發表於2021-02-22

CAP

CAP 理論是分散式系統中的一個老生常談的理論了,最早由 Eric Brewer一個講座中提出。在這個講座中,在傳統 ACID 理論以及當時比較流行但是比較抽象的的設計指導理論 BASE 理論(當時的 BASE 理論還很抽象,直到好幾年後才出現一份比較權威的被廣泛接受的 BASE 理論完整解釋和設計)的類比中,提出

  • C(Consistency,一致性):在一個分散式的系統中,同一個資料所有備份,在同一時刻是否有相同的值。也就是,對於同一個資料的讀寫,是否立刻對於所有副本都能看到一致的結果。一種比較常見的強一致性實現就是,在看到一致的結果之前,寫請求不返回,讀請求阻塞或者超時。
  • A(Availability,可用性):在叢集中一些節點故障時,叢集還可以響應讀寫請求
  • P(Partition-tolerance,分割槽容忍性):分散式系統具有多個節點,如果節點間網路中斷,就會造成分割槽

並且提出了,CAP 並不能全部滿足,而是一般選兩個滿足

之後,Seth Gilbert 以及 Nancy Lynch一篇 Notes 中,證明了 CAP 並不能同時都滿足。並且,將 CAP 定義的更加清晰:

  • C: 需要滿足原子一致性,也就是任何讀寫都是具有原子性的,也就是對於同一個資料的寫之後的讀取,一定能讀取到寫的值,也就是最新的值
  • A:對於所有成功的請求,都需要在有限的時間內返回,也就是成功請求是有效的,可終止的。
  • P:可能節點間傳輸丟失一些訊息

CA 系統

也就是不允許分割槽的系統,也其實就不是分散式系統,而是單機系統。例如單機資料庫,或者是共享儲存資料庫,比如 Aurora DB 類似的思路設計的資料庫,共享同一份儲存,上面建立不同的 MySQL 程式,一個 MySQL 讀寫,其他的只讀,由於使用的同一塊儲存,並且只有一個 MySQL 程式寫入,滿足 ACID 的事務特性,能保證強一致性,以及可用性。

CP 系統

也就是不要求高可用性,但是要求強一致性的系統,哪怕當前業務不可用,也不能出現資料不一致的情況。並且,如果節點間傳輸訊息丟失導致沒有同步成功,或者重試,或者返回更新失敗,回滾更新請求

CP 的一種實際應用就是分散式鎖,一般的,如果沒有獲取到鎖,或者獲取鎖失敗,我們都會選擇阻塞等待,或者直接失敗,而不會冒著可能會有併發危險而去執行業務。並且,分散式鎖必須保持所有節點看到的鎖狀態一致,不能有差異,否則認為獲取鎖失敗。

同時,大部分分散式資料庫都是 CP 系統,但是他們的一致性協議方案是不同的,常見的例如 Paxos,2PC,3PC,RAFT等等。

AP 系統

也就是要求高可用性,但是不用強一致性的系統。在這種情況下,一旦分割槽發生,節點間的資料可能不一致,每個節點用自己的本地資料繼續提供服務。這樣情況下,可能會出現資料不一致,系統一般會實現最終一致性。也就是在分割槽結束後,通過一些機制將資料同步。

基本上具有多層快取的系統,都是 AP 的系統設計。例如 DNS,客戶端快取,瀏覽器快取以及程式內快取等等。

一個 CP 與 AP 系統的對比

一個比較經典的例子就是 Zookeeper 作為註冊中心和 Eureka 作為註冊中心。

假設註冊中心有兩個介面,一個是註冊例項,一個是讀取例項。

如果以 Zookeeper 為註冊中心,對於註冊例項請求也就是更新請求,採用的是過半寫以及 2 PC 的同步機制。
image

只有過半 2PC 更新成功,這個註冊請求才成功,這樣讀取每個節點都會讀取到這個更新請求,否則會回滾已經更新的節點。並且每個節點資料是一致的。如果過半的節點不可用,那麼整個叢集都不能處理註冊例項請求以及讀取例項的請求。這樣保證的強一致性,但是可用性是打了折扣的。

如果以 Eureka 為註冊中心,註冊請求發到一個 Eureka 例項上之後,這個 Eureka 會轉發到叢集內其他 Eureka 節點。

image

即使某些節點失敗,也不會將已經更新的回滾。並且無論叢集內哪些 Eureka 掛了,也不會影響其他正常的 Eureka 繼續服務工作,雖然可能讀取到比較老的資料,以及有一些資料不一致。

目前的 CAP 理論

隨著技術的不斷髮展以及理論的不斷完善,我們發現,分割槽並不是會經常出現的情況,大部分情況下,如果我們忽略 P ,其實就是可以實現 CA 共存的情況。如果分割槽是可以感知的,納悶我們可以提前制定響應策略,例如進入服務降級限制某些操作,通過恢復補償邏輯修正資料不一致。

在 CAP 基礎上演變的 PACELC 理論,就是針對這種情況的更為實際的指導意見。在出現分割槽的情況下,取前半部分,其實還是 CAP 理論。如果不出現分割槽的情況,也就是大部分的情況下,我們考慮 L(Latency,延遲) 與 C(Consistency 一致性)的權衡。

微信搜尋“我的程式設計喵”關注公眾號,每日一刷,輕鬆提升技術,斬獲各種offer

image

相關文章