正確理解CAP定理與ACID,BASE的關係

參考文章

CAP theorem - Wikipedia
Please stop calling databases CP or AP
ACID - Wikipedia
Eventual_consistency - Wikipedia
CAP和BASE理論

前言

特定理論的英文縮寫一向是程序員裝逼最趁手的工具, 兩個程序員交流時, 如果一方想要拋出一個自己瞭解過的高級概念並試探性地進行智商碾壓時, 必然要在談吐間夾帶一些英文字母, 並暗示你, 如果你沒聽過這個英文縮寫, 就快點接受我的觀點。

CAP, BASE 就是上述的裝逼利器之一, 而且有點爛大街。 很多程序員甚至不屑於過多使用它們, 因爲他們彷彿是分佈式系統的最容易掌握的入門知識點。

遺憾的是, 很多人爲了滿足裝逼需求, 只是粗淺地翻閱一些網絡博文, 對這幾個概念沒有準確理解, 就誇誇奇談。本文旨在幫助有興趣的初學者, 正確而清晰地掌握這幾個並不粗淺的概念及其關聯的其他知識點。如下兩個誤解可供讀者檢驗是否有必要閱讀本文。

CAP 定理誤用一

在分佈式系統設計中, 必須選擇性放棄C、A、P 三種性質中的一種(錯誤!!!

CAP 定理誤解二

設計系統時, 我們要麼追求設計一個 CP 系統, 要麼追求設計一個 AP 系統(不準確

CAP 定理(不建議稱爲 CAP 理論)

首先值得強調的是, CAP, ACID, BASE 這三個常常關聯出現的英文縮寫中, CAP 的地位是最高的, 只有 CAP 可以稱作定理(Therom), 沒錯, 就是數學含義的定理, 它是指受邏輯限制的證明爲真的陳述, 幾乎不容反駁, 除非你推翻定理證明的前置定理和基本的邏輯學。 所以這裏強烈建議讀者看到 CAP, 就將其稱爲定理, 而非一種理論, 因爲不是所有的理論都被嚴格證明爲真。

CAP 定理最先是2002年由加州伯克利分校的 Eric Brewer 提出的一個猜想, 而這一猜想的證明,是2年之後由麻省理工學院的 Seth Gilbert 和 Nancy Lynch 證明的, 光是這一點就足以說明這一定理並不是一個簡單的概念。

CAP 定理的出現就像一盞明燈, 在茫茫的學術海洋中, 爲衆多探索者指明瞭清晰的方向, 避免了很多不必要的嘗試與研究

它的結論非常簡單: 一個分佈式系統不可能同時滿足 C, A, P 這三個字母分別描述的三個屬性, 只能滿足其中兩個。

上面這個部分, 幾乎所有知道這個概念的人, 都能正確背誦,但是很多人都不能準確的描述 C, A, P 每個英文字母所代表的含義。 要知道一個數學定理的概念定義一定是非常精確的, 含義的輕微修改都可能導致定理的失效, 以致於提出這個概念猜想 Eric Brewer 本人都在公開發布的文章中承認,有關 CAP 定理指導分佈式系統設計 “三選二” 的說法,是一種具有誤導性, 或者錯誤的定理應用。

在這裏插入圖片描述

一致性(Consistency)

Consistency: Every read receives the most recent write or an error

一致性: 每一次讀請求都能獲得最近一次寫操作的結果或是一個錯誤。

上面這句話看起來非常簡單, 但是讀者必須要注意把它放到分佈式系統的語境中進行理解。

  1. 多個讀請求, 要允許來自不同的客戶端。
  2. 多個讀請求, 可能被轉發到不同的服務器結點上(系統對外暴露哪些結點, 由系統設計者定義,但通常,分佈式系統都會定義多個結點接收客戶端請求,並且允許水平擴展, 否則就會存在單節點瓶頸, 失去了分佈式系統設計的初衷)
  3. 多個讀請求中可能穿插着任意的寫請求,讀寫請求的發起順序和到達系統的順序是不被保障的。
  4. 如果讀請求無法滿足上面的要求, 服務器可以拒絕讀請求, 也就是返回了錯誤。

整個系統的讀寫交互過程可能是如下這樣雜亂無章的, 當然, 你也可以對外提供一個專用結點, 用於接收所有客戶端的請求, 但是很明顯, 你需要考慮如何解決,單節點發生故障導致整個系統不可用的問題
在這裏插入圖片描述
需要再三強調的是, CAP 定理中的 Consistency , 與 ACID 中的 Consistency 是完全不一樣的概念!!! , 這一點在本文後續會再次被強調。

此處的一致性含義更不容易被誤讀的一種命名是 “Linearizablity” , 其含義是:

  • 任意一個寫請求A 被系統成功處理後, 系統緊接着收到的讀請求B, 無論是系統中的哪個結點收到的(只要設計者允許該結點接收讀請求),都必須能成功感知到 A 操作所帶來的影響。

可用性(Availability)

Availability: every request received by a non-failing node in the system must result in a [non-error] response

可用性: 每一次被非失敗結點收到的請求, 都可以獲得一個非錯誤的正常響應。

關於可用性這一特性, 也是不少人沒有完全理解的特性之一。 簡單的問 2 個問題:

  • 滿足可用性的系統, 是一個 7 * 24 小時百分之百不會終止工作的系統嗎,這樣的系統存在嗎
  • 如果系統中的部分結點允許失敗, 這個比例有什麼要求嗎

顯然, 沒有任何一個系統,可以保證百分之百不失敗, 這裏的可用性其實描述的是:

  • 對客戶端而言, 你的分佈式系統, 可能內部已經有部分甚至大量結點宕機, 但如果還有結點允許處理客戶端請求且能成功接收請求時, 被收到到的每個請求都是否能成功處理並予以返回

分區容忍性(Partition tolerance)

Partition tolerance: The system continues to operate despite an
arbitrary number of messages being dropped (or delayed) by the network
between nodes

分區容忍性: 即使系統內部結點間的任意數量的通信信息都可能被延遲或丟失, 整個系統也能正常運作。

這一特性相比前兩個特性不復雜, 但是依舊有不少人將其錯誤理解爲某分區,或某部分結點無故障時, 整個系統依舊正常運行。

正確理解這一特性的關鍵點是, 該特性描述的是通信故障對系統的影響而非結點故障對系統的影響。 由於分佈式系統中存在多個結點, 假如你試圖在多個結點中同步數據會進行某種協同指令操作, 必然涉及到網絡通信, 而網絡通信是沒有必達保障的, 分區的概念描述的是一部分結點間失去聯繫, 但是這些結點還可以和外部通信的狀態。

例如下圖, Server2, Server3 無法與 Server1 正常通信,但是Server2,Server 3 之間可以相互通信, 導致整個系統形成了兩個網絡分區,這兩個網絡分區均可以和外界客戶端正常交互。
在這裏插入圖片描述
分區容忍性即是在詢問,這種情形下, 你的系統還能否如你所期待的那樣 “正常” 工作。

正確理解 CAP 定理

從字面上來說, CAP 定理好像是在說一個任意 “三選二” 的事情, 但事實上, 只要你的系統是基於互聯網通信, 那麼信息都沒有必達保障, 都會存在延遲會丟失信息的問題, 所以你設計的系統, 是一定需要滿足 “Partition Tolerance” 這一屬性的, 所以在這一屬性上, 你其實並沒有什麼選擇

那麼是否就可以說, CAP 定理指導我們要麼設計一個 CP 系統, 要麼設計一個 AP 系統呢?

很遺憾,這種說法也不正確。 因爲 CAP 定理中的 Consistency 與 Availability 實際含義是一個非常精確, 也就是我們之前提到的 Linerazability, 很多系統在這種嚴格定義下, 既不是 AP 系統也不是 CP 系統

一個簡單的例子是 ZooKeeper, 由於 ZooKeeper 使用到了共識算法(Consensus Algorithm), 不少人理所當然的認爲它是一個 CP 系統, 但是如果嚴格使用 CAP 定理中的定義來審視, 在一般情況下,它既不 CP, 也不 AP。 原因如下:

  • 客戶端可以連接到 ZooKeeper 系統中的多個服務器,默認情況下,你的讀請求並不能返回反生在其他服務器的剛剛的寫操作結果。 此時, ZooKeeper 不滿足 CAP 中的 C 屬性

  • 而當網絡分區發生時, 含有少數結點的分區只能處理讀請求, 無法成功處理寫請求並進行響應。 此時, ZooKeeper 不滿足 CAP 定理中的 A 屬性。

但是, 如果在發給 ZooKeeper 的讀請求前, 都追加一個 sync 指令, ZooKeeper 系統就可以滿足 CAP 定理中 C 的屬性。

綜上, 如果 CAP 定理不能簡單解讀爲一個指導我們 “三選二” 設計系統的定理, 它的核心價值是什麼呢? 我們可以試着從它的近似不嚴謹證明的過程去理解。

最簡化的情況下, 我們有兩個系統結點, 能夠分別處理客戶端的讀寫請求, 由於網絡通信是不可靠的, 我們看網絡分區時會發生什麼。
在這裏插入圖片描述
假設這裏我們 結點A 和 結點B 相互存儲了對方的副本數據, 我們要求系統滿足 CAP 中的 AP 屬性, 即在這種情況下, 兩個結點都要能正常處理客戶端發來的請求, 看能否實現 C 的屬性。

當網絡分區發生時, 結點B 收到的讀請求, 是無論如何無法感知到發生在 結點 A 的寫操作的。 所以結點B 對於 2.b 這一讀請求, 要麼返回一個不滿足 C 屬性的響應,要麼返回一個錯誤提示。 但是如果返回一個錯誤提示的話, 顯然違背了 A 屬性要求正常工作的結點不能返回錯誤信息的要求。

粗一看, 好像這個過程指導我們魚(Consistency)與熊掌 ( Avaliablity) 不可兼得

但設想一下, 我們如果允許 結點B 返回錯誤信息並附帶一個指示, 指導客戶端向其他結點發送請求呢?系統是否某種意義上又是 “可用” 的呢? 它只是不滿足CAP定理數學意義上的 可用性(Avaliablity)

從上面的例子可以看出來, CAP 定理的核心是向我們揭示了是一個網絡通信不可靠的環境下, 分佈式系統設計所需要面臨的設計困境。 而不是讓我們簡單的把系統設計目標定位 AP 或 CP, 更不是將已有的分佈式系統歸類爲 AP 或 CP 進行選用。 它引導我們去思考分佈式系統設計中的核心矛盾, 這也就引出了後續的關聯知識點 ACID 與 BASE 。

ACID 四性質

前面強調過, CAP 定理中的 Consistency 和 ACID 性質裏的 Consistency 是兩種完全不同的概念, 但是爲什麼又要把他們放在一起討論呢 ?

原因是, CAP 定理向我們揭示的系統設計中的 Linearizability 問題, 常常會進一步轉化爲, 如何使分佈式系統實現多結點的副本數據一致性, 而多結點的副本數據一致性問題, 往往又會轉化爲如何實現分佈式事務問題, 即一個寫操作如何確保它只要成功, 就同時在多個結點成功, 一旦失敗, 就在多個結點同時失敗。 而 ACID 這四個性質, 恰恰就是用於準確描述事務的。

ACID 和 CAP 有點相似的地方時, 它也提到了一些需要被計算機系統滿足的性質,字面上 acid 這一單詞作爲形容詞, 也是“酸性的” 含義, 可以輔助我們記憶這個概念描述的是一種性質而非一種定理

如果一個數據庫系統的一系列操作能夠滿足 ACID 這四個屬性, 我們就可以將其稱爲一個事務:

  • Atomicity 原子性
    • 一個事務中的多個操作對外表現得就像一個化學原子一樣, 不可分割, 要麼都成功, 要麼都失敗
  • Consistency 一致性
    • 這是四個屬性中最容易被誤解的一個屬性
    • 數據庫事務的一致性概念,最早在 Jim Gray 的論文中提出, 原文如下
    • Consistency: the transaction must obey legal protocols.
    • 上面的這個定義其實說的非常寬泛, 一種簡單的理解是, “一致性” 這一性質要求一個事務成功後, 只能把數據庫的狀態從一個正確的狀態轉移至另外一個正確的狀態。
    • 那麼如何定義這個正確性呢, 一部分人認爲這個正確性應該定義爲數據庫各種強制性的約束(比如主鍵約束, 外鍵約束), 即發生違反約束的情況應當導致事務回滾。 另一部分人認爲, 這個正確性應當推廣到應用層的業務含義約束, 比如, 轉賬前後, A賬戶 + B賬戶的錢一定要是固定的一個值。
    • 這兩種正確性的理解筆者認爲均可, 都不妨礙對於事務這一概念的理解。需要注意的是, 該一致性的概念和 CAP 理論中的一致性, 並不一樣!!!
    • CAP理論中的一致性, 強調的是一個讀寫操作線性序列化的概念, 即一次讀操作, 必然能夠返回最近一次成功的寫操作的影響。 而 ACID 中的一致性,強調的是, 一個事務的開始前狀態和結束後的數據庫狀態, 都需要滿足數據庫正確性的定義
  • Isolation 隔離性
    • 併發執行的多個事務結束後使數據庫達到的狀態應當和這些事務不併發, 依次順序執行的結果一樣。
    • 這一性質主要關注事務併發執行的效果, 比較好理解, 不作過多贅述
  • Durability 持久性
    • 事務一旦被成功提交, 即使立刻發生系統宕機, 已經提交的事務記錄應當依舊有效。

關於 ACID 事務在單機數據庫中如何實現, 這裏不作贅述,需要我們知道的是, 分佈式系統如果想實現一個 ACID 事務, 並不容易, 被提出的代表性方案是 二階段提交協議(Two-Phase Commit)。筆者在另外一篇博文中也有介紹 正確理解二階段提交協議

基於 ACID 分佈式事務不易實現的背景下, BASE 作爲一個 ACID 的替代選項被提了出來

BASE 四性質

BASE 單詞作爲形容詞, 字面上恰好是 ACID 的化學對立面, “鹼性的”, 非常容易記憶。 但是其中的性質與 ACID 的關係卻不是對立的。 展開來說, BASE (Basically Available, Soft state, Eventual consistency) 描述的三個性質:

  • Basically Available 基本可用
  • Soft state 柔性狀態
  • Eventual consistency 最終一致性

顯而易見的是, BASE 所描述的約束, 是比 ACID 更寬鬆的約束, 一個滿足 ACID 的系統, 必然是輕易滿足 BASE 的, 反之則不能成立。 所以酸鹼性的記憶僅限於名詞的關聯記憶, 不可做含義引申。

需要指出的是, BASE 這一提法, “最終一致性的概念”, 並不像 ACID 那樣, 每一個都有精確且獨立的定義。 最早提出這一縮寫的是 eBay 架構師 Dan Pritch-ett 在 ACM Queue 這一雜誌上發佈的文章BASE: An Acid Alternative, 文章中 Soft State 與 Eventrually Consistent 也被當做是幾乎相同的概念。

所以關於 BASE 理論, 不必像 CAP 或 ACID 那樣精確的探究每一個字母的含義, 只要把握住最終一致性這一核心概念, 並且理解其放鬆了 CAP 定理中可用性定義的即可。

筆者個人也不建議把 BASE 作爲一個常用的名詞來描述問題, 畢竟一切不清晰的定義, 都是誤解和錯誤產生的來源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章