(翻譯) CAP 理論 FAQ
CAP 理論 FAQ
0. 關於這個文件
沒有其它比CAP理論更引人注意的話題了, 這個FAQ的目的, 是說明對於CAP, 當前哪些是已知的, 並幫助那些剛接觸這個理論的人快速瞭解, 並解決一些錯誤的觀念和常見的誤解.
當然, 很可能我的認知是膚淺甚至完全錯誤的, 歡迎任何評論和糾正.
1. CAP理論的來源是什麼?
Eric Brewer 博士在2000年的 Principles of Distributed Computing 會議上作了一個報告, 標題是"Towards Robust Distributed Systems", 在這個報告中, 他提出了CAP 理論 - 那時候這個理論還未被證明 - 描述了在分散式系統中一致性和可用性之間的矛盾.
兩年後, 在MIT研究分散式系統的 Seth Gilbert 和 Nancy Lynch 教授在他們的論文“Brewer’s conjecture and the feasibility of consistent, available, partition-tolerant web services”中證明了CAP理論.
2. CAP理論到底說了什麼?
CAP定理(以下簡稱 CAP)指出, 在非同步網路中實現的讀寫儲存, 不可能同時滿足以下三個特性:
- 可用性 - 是否對於資料儲存的每個請求都會成功執行?
- 一致性 - 對於資料的讀寫執行, 是否從每個分散式節點所觀察到的都是一致的, 或者是可線性化一致的?
- 隔離容忍性 - 分散式系統之間的通訊是否允許丟失任意訊息?
更通俗地說, CAP定理告訴我們, 無法建立一個既能響應每個請求又能每次都返回預期結果的分散式儲存系統. 這是一個不可能的結果, 它告訴我們, 我們在努力嘗試的目標實際上是不可實現的. 這很重要, 因為過去幾年已經建立和正在建立的許多分散式系統都會受到這個理論的影響. 但它並不意味著我們不能在這些限制下建立有用的系統. 細節是魔鬼, 在你開始"是的, 但是..."之前, 確定自己已經明白什麼是CAP理論允許和不允許的.
3. 什麼是 ‘讀寫儲存’?
CAP理論特別關注的一種結構, 叫 register, 即嵌入式領域中的暫存器. 暫存器是一種具有兩種操作的資料結構:
- set(X) 將暫存器的值設為 X
- get() 返回暫存器中最新的值
一個KV儲存可以看成是一組暫存器的集合. 即使暫存器看起來非常簡單, 但它體現了分散式系統做的事情本質 - 寫入資料和讀取資料.
4. 原子一致性(Atomic Consistency), 線性一致性(Linearizable Consistency)是什麼含義?
原子一致性(Atomic Consistency), 或者說線性一致性(Linearizable Consistency), 是關於客戶端在執行讀寫操作時返回值的可見度問題, 體現在暫存器上, 就是在被所有的分散式節點訪問時, 響應和請求是基於同一個時鐘順序的(注: 這是強一致性, 理想狀態的一致性).
例如一個執行由多個客戶端的操作組成, 這些操作可能是併發的, 在原子一致性的要求下, 這個執行的結果必須等同於所有操作單次序列(按順序,一個接一個)執行的結果. 這是一個很強的約束, 與其它的約束是衝突的, 除了其他約束之外, 它還排除了最終一致性(EC, 允許在寫入變得可見之前有延遲). 所以在EC下, 可能會出現:
set(10),
set(5),
get() = 10 // 但是讀取到的是10
在原子一致性下, 上面的流程是不可能出現的.
原子一致性會確保暫存器的外部訪問順序, 也就是說, 如果A讀取了X, 並且A能與B通訊, B去讀也能讀取到一致的結果. 在稍微弱一些的約束下(例如順序一致性)這個結果可能不一定成立. 下面我們做如下的操作:
B:set(5), A:set(10), A:get() = 10, B:get() = 10
這體現了操作的原子一致性, 但是下面這種情況就不是
B:set(5), A:set(10), A:get() = 10, B:get() = 5
雖然這和下面的序列化操作是一樣的
B:set(5), B:get() = 5, A:set(10), A:get() = 10
在第二個例子中, 如果A在讀取暫存器後告訴B關於暫存器的值(10), B會錯誤地認為有另外的操作在 A:get() 和 B:get() 之間把暫存器值改成了5. 如果不允許節點間通訊, B 並不知道 A:set, 並且要保持讀寫的一致, 就像 B:get() 發生在 A:set 之前一樣.
Wikipedia 有更多的說明. Maurice Herlihy 1990年的論文原文在這裡.
5. 什麼是非同步(asynchronous)?
非同步網路, 就是對節點處理訊息或網路送達訊息的時間沒有限制的網路, 這個定義帶來的影響, 就是無法判斷一個節點到底是宕機了, 還是它的訊息被延遲了.
6. 什麼是可用(available)?
一個數據儲存的可用, 體現在所有的get和set請求最終都會返回響應. 這個響應不是指返回錯誤, 因為如果用這個判斷的話, 很明顯一個系統可以只靠返回錯誤而保證可用性. 因為可用性對於響應的時效性並沒有約束, 所以系統可以花任意長的時間來處理一個請求, 但是必須最終返回響應.
要注意到, 這是同時是一個強約束, 也是一個弱約束. 強約束是指所有的請求都必須正確處理並返回, 弱約束是指處理時間的長度沒有限制.
7. 什麼是分割槽隔離(partition)?
分割槽隔離, 是指分散式系統中一個或多個節點間的通訊出現故障, 導致訊息丟失(不是延遲, 如果訊息最終到達了, 就不屬於這種情況).
這個詞有時用於描述一個時間區間, 這個時間區間內兩組節點之間的訊息傳遞都失敗了. 這是一種更嚴格的失敗模型, 可以稱這種隔離為完全隔離.
CAP的證明依賴於完全隔離, 在實際應用中, 如果所有的訊息都通過一個元件, 如果這個元件失效, 那麼這兩個節點的所有訊息傳送都會失敗.
8. 為什麼 CAP 理論是正確的?
CAP理論的基本思想是, 如果存在分割槽隔離的情況, 一個客戶端向一側分割槽寫入資料, 那麼對另一分割槽的任何讀取都不可能讀取到這些寫入. 這時候就會面臨著一個選擇: 是用可能過時的資料來響應讀取, 還是等待(可能永遠等待)來自另一側分割槽的訊息而影響可用性? 基於這個構造的場景, 我們描述了一個分散式系統無法同時保持一致性和可用性的情況. CAP理論受到這麼多關注的一個原因, 是這個場景是很可能出現的, 當網路裝置出現故障時就會發生分割槽間的完全隔離.
9. 什麼時候系統不得不放棄 C 或者 A?
CAP理論僅僅說明在某些情況下一個分散式系統必須放棄A或者C. 這屬於比較極端的情況, 而理論並沒有說明發生這種極端情況的可能性有多大. C 和 A 都是強約束: 只有操作100%滿足時才成立. 只要有一個非一致的讀取或失敗的寫入, 都會使 C 或 A 的保證無效. 但是在極端情況之外是很容易滿足 C 和 A 同時成立的.
由於大多數分散式系統都會長時間執行, 在整個生命週期中處理數百萬千萬的請求, 這期間大概率會遇上某個極端情況, 瞭解CAP理論, 就可以提前瞭解在哪個方面會出問題, 並進行準備.
10. 為什麼當我說我的系統是CA時, 一些人會不滿意?
Brewer的觀點, Gilbert的論文, 以及很多其他人的觀點, 通常把C, A和P作為等同的特性, 並在其中可以任意選擇兩個. 然而這是一種誤導性的表述, 因為"分割槽隔離的容忍性"是無法避免的: 分散式系統幾乎不可避免地會遇到節點間通訊障礙. 所以CAP更適合理解為: 構建一個可能出現分割槽隔離的系統時, 如何做出權衡. 實際上,這就是分散式系統: 沒有100%可靠的網路, 所以(至少在分散式環境中)現實中並不存在CA系統.
所以, 將定理改一下可能更有指導意義: 一個分散式系統出現通訊故障時,不可能同時兼顧A和C.
有些系統不會出現分割槽隔離,例如單節點的資料庫伺服器, 然而這些系統通常與CAP適用的環境不相關. 如果您將一個分散式資料庫描述為"CA"系統, 那麼您對分散式系統和CAP理論還存在誤解.
11. 如果訊息不會丟失呢?
Gilbert的論文中, 一個可能令人驚訝的結論是: 在一個非同步網路中, 讓一個暫存器保持永遠可用是無法實現的, 並且只有當訊息不會丟失時才能保持一致性.
這個結論基於非同步網路的屬性, 其思想是無法判斷一個訊息是否已經丟失, 所以一個節點無法一邊等待一邊維持可用性, 這種情況下只要響應了, 結果一致性就被破壞了.
12. 我的網路真的是非同步的嗎?
可以說, 是的. 不同的網路有不同的特徵.
如果
- 您的節點沒有時鐘(不太可能), 或者它們的時鐘可能會偏離(更有可能)
- 系統程序可能會任意延遲訊息的傳遞(由於重試或GC暫停)
那麼您的網路就可以被認為是非同步的.
Gilbert和Lynch還證明, 在部分同步系統中, 節點共享但時鐘不是同步的, 並且每個訊息的處理時間都有限制, 因此不可能實現可用的原子性儲存.
然而,來自#8的結果在部分同步模型中不成立, 實現始終可用的原子性儲存是可能的, 並且當所有訊息都不會丟失時可以保證一致性.
原文
Gilbert and Lynch also proved that in a partially-synchronous system, where nodes have shared but not synchronised clocks and there is a bound on the processing time of every message, that it is still impossible to implement available atomic storage.
However, the result from #8 does not hold in the partially-synchronous model; it is possible to implement atomic storage that is available all the time, and consistent when all messages are delivered.
13. FLP 和 CAP 之間有什麼聯絡?
FLP理論(Fischer, Lynch 和 Patterson)是三十年前提出的一個非常有名的"不可能性(Impossibility)"理論, 這個理論確立了共識(一致性, 讓所有的節點達成一致)問題: 如果有一個非同步網路, 這個網路的節點可能會失效, 那麼這種一致性是無法實現的.
FLP理論與CAP理論沒有直接關係, 儘管它們在某些方面是相似的: 兩者都是對於分散式系統中無法解決的問題的"不可能性"結論. 細節是魔鬼, 下面是FLP與CAP的一些不同之處:
- FLP允許一個節點失敗, 這個節點與系統完全隔離, 並且不必響應請求
- 否則, FLP不允許訊息丟失, 網路只是非同步但是沒有訊息丟失
- FLP 用於處理共識問題, 這是一個類似的, 但不同於原子性儲存的問題
14. C 和 A 是可以調節的嗎?
在設計分散式系統時, 可以對一致性或可用性降低標準而實現一個"可用"的系統. 實際上CAP理論的意義在於, 這是不可避免的,任何設計和構建的系統都必須對其中的一項或兩項作出妥協. 作為設計者, 則需要弄清楚什麼時候並且如何做.
關心一致性的系統會選擇降低可用性, 比如ZooKeeper. 其他系統, 例如Amazon的Dynamo, 為了保持高度的可用性, 則選擇降低一致性.
如果不能滿足CAP理論中的理想狀態假設, 就必須重新證明這個不可能性結論.
原文
Once you weaken any of the assumptions made in the statement or proof of CAP, you have to start again when it comes to proving an impossibility result.
15. 一個故障節點是否等效於一個被隔離的節點?
不等效. 一個故障節點通常不需要再響應請求. CAP理論並不允許節點"故障"(這是一個強假設, 因為實際上節點不發生故障是不可能的).
在一個非同步網路中當N-1個節點發生故障時, 可以證明原子性儲存的不可能性結論. 這個結論會對設計上的權衡造成影響: 是保證寫入的節點數量(效能問題), 還是容錯能力(可靠性問題)
16. 一個執行很慢的節點是否等效於一個被隔離的節點?
不一樣: 訊息最終會被傳遞到一臺很慢的節點, 但永遠不會被傳遞到一臺被隔離的節點. 實際上, 很難區分訊息丟失(節點故障)和節點很慢的情況, 這也是CAP, FLP和其它分散式理論為什麼成立的原因.
17. 我是否能繞過或者戰勝 CAP 理論?
不能, 您可能設計了一個還未受到明顯影響的系統, 這很好.
來源
https://www.the-paper-trail.org/page/cap-faq/, 作者 Henry Robinson