CAP定理 —— 一個不可能的選擇
“便宜、快速、好:選擇其中兩個”?
CAP定理:你不能同時擁有蛋糕并吃掉它。
- 一致性:蛋糕始終是同樣的口味。
- 可用性:蛋糕始終可以被吃掉。
- 分區(qū)容錯性:蛋糕可以被切成塊并共享。
CAP定理將類似的推理方法擴展到分布式系統(tǒng)中;具體而言,它指出分布式系統(tǒng)只能提供三個中的兩個理想特性:一致性、可用性和分區(qū)容錯性(CAP中的字母'C','A'和'P')。
將數(shù)據(jù)同時保存在多個節(jié)點上的網(wǎng)絡(luò),無論這些節(jié)點是實際的還是虛擬的計算機,都被稱為分布式系統(tǒng)。
在開發(fā)云應(yīng)用程序時,了解CAP定理非常重要,因為所有云應(yīng)用程序都是分布式系統(tǒng)。
CAP的基本概念
讓我們更深入地了解CAP定理對分布式系統(tǒng)的三個特性的概念。
一致性
無論客戶端連接到哪個節(jié)點,它們總是同時看到相同的數(shù)據(jù),這就是一致性。
為了實現(xiàn)這一點,每次將數(shù)據(jù)寫入一個節(jié)點時,必須立即將其發(fā)送或復(fù)制到系統(tǒng)中的所有其他節(jié)點,然后才能認(rèn)為寫入已經(jīng)“成功完成”。
可用性
任何請求數(shù)據(jù)的客戶端都會獲得響應(yīng),即使網(wǎng)絡(luò)中的一個或多個節(jié)點不可用。這就是可用性。
換句話說,分布式系統(tǒng)中的每個運行節(jié)點都將毫無例外地對每個請求提供合法的答案。
分區(qū)容錯性
分布式系統(tǒng)內(nèi)部的通信中斷稱為分區(qū)。這可以被看作是系統(tǒng)中兩個節(jié)點之間的連接丟失或暫時延遲。
術(shù)語“分區(qū)容忍性”是指盡管在構(gòu)成系統(tǒng)的各個節(jié)點之間的通信中出現(xiàn)任意數(shù)量的故障,集群的功能仍必須得到維護(hù)。
不同NoSQL數(shù)據(jù)庫的CAP原則
img
NoSQL數(shù)據(jù)庫是在分布式網(wǎng)絡(luò)上運行的應(yīng)用程序的最佳選擇。與垂直可擴展的SQL(關(guān)系型)數(shù)據(jù)庫相比,NoSQL數(shù)據(jù)庫是水平可擴展且分布式設(shè)計的。這意味著它們能夠在由多個鏈接節(jié)點組成的發(fā)展網(wǎng)絡(luò)上快速擴展。
現(xiàn)在,NoSQL數(shù)據(jù)庫根據(jù)它們提供的兩個CAP原則進(jìn)行分類,這兩個原則分別是:
CP數(shù)據(jù)庫提供一致性和分區(qū)容忍性,但以犧牲可用性為代價。如果在任意兩個節(jié)點之間發(fā)生分區(qū),系統(tǒng)需要將非一致的節(jié)點停止(即使其無法訪問),直到分區(qū)問題得到解決。
AP數(shù)據(jù)庫在數(shù)據(jù)的一致性方面存在犧牲,但提供可用性和分區(qū)容忍性。當(dāng)分區(qū)發(fā)生時,網(wǎng)絡(luò)中的所有節(jié)點仍然可訪問,但靠近分區(qū)開頭或結(jié)尾的節(jié)點可能提供比其他節(jié)點更舊的數(shù)據(jù)版本。(一旦分區(qū)問題得到解決,AP數(shù)據(jù)庫通常會重新同步節(jié)點,以糾正可能引入到系統(tǒng)中的任何不一致性。)
CA數(shù)據(jù)庫確保數(shù)據(jù)在系統(tǒng)中的所有節(jié)點之間保持一致和可訪問。然而,如果系統(tǒng)中的任意兩個節(jié)點之間存在分區(qū),它無法完成這個任務(wù),因此無法提供容錯性。
由于分區(qū)在分布式系統(tǒng)中是不可避免的,我們故意將CA數(shù)據(jù)庫類型放在列表的最后。因此,雖然可以在理論上討論CA分布式數(shù)據(jù)庫的概念,但實際上,這樣的數(shù)據(jù)庫根本不存在。然而,如果你覺得你的分布式應(yīng)用需要CA數(shù)據(jù)庫,并不意味著你不能擁有這樣一個數(shù)據(jù)庫。
包括PostgreSQL在內(nèi)的各種關(guān)系型數(shù)據(jù)庫都可以提供一致性和可用性,并可以在多個節(jié)點上進(jìn)行復(fù)制以進(jìn)行分布式部署。
CAP定理和MongoDB
MongoDB將數(shù)據(jù)存儲為BSON(二進(jìn)制JSON)文檔,使其成為常見的NoSQL數(shù)據(jù)庫管理系統(tǒng)。它廣泛用于大規(guī)模、實時、分布式應(yīng)用。
MongoDB是一個CP數(shù)據(jù)存儲,因為它能夠在保持?jǐn)?shù)據(jù)一致性的同時解決網(wǎng)絡(luò)分區(qū)問題,但以犧牲可用性為代價,正如CAP定理所描述的那樣。
在MongoDB中,一個復(fù)制集(replica set)只能有一個主節(jié)點來處理所有寫操作。復(fù)制集中的次要節(jié)點復(fù)制主節(jié)點的事務(wù)日志,并使用它來更新自己的數(shù)據(jù)副本。客戶端默認(rèn)從主節(jié)點讀取數(shù)據(jù),但可以通過設(shè)置讀偏好來更改這一行為。
如果原始節(jié)點故障,最近操作日志最多的次要節(jié)點將被提升為主節(jié)點。只要所有從節(jié)點都趕上了新的主節(jié)點,集群就會恢復(fù)可訪問性。在此期間,沒有客戶端可以發(fā)送寫請求,因此數(shù)據(jù)在整個網(wǎng)絡(luò)上是同步的。
CAP定理(AP)和Cassandra
Apache軟件基金會開發(fā)和分發(fā)Cassandra,這是一個自由開源的NoSQL數(shù)據(jù)庫。它以寬列數(shù)據(jù)庫的形式進(jìn)行分布式數(shù)據(jù)存儲。由于其無主節(jié)點的設(shè)計,Cassandra沒有像MongoDB那樣的單點故障。
Cassandra是一個AP數(shù)據(jù)庫,因為它滿足了一些但不是所有的一致性、可用性和分區(qū)容忍性(CAP)要求。由于缺乏主節(jié)點,Cassandra集群中的所有節(jié)點始終處于運行狀態(tài)至關(guān)重要。另一方面,Cassandra通過允許客戶端隨時向任何節(jié)點寫入數(shù)據(jù)并迅速解決不一致性問題來提供最終一致性。
Cassandra具有“修復(fù)”功能,以幫助節(jié)點趕上其對等節(jié)點,因為只有在網(wǎng)絡(luò)分裂的情況下數(shù)據(jù)才會變得不一致,并且不一致性會迅速得到糾正。然而,持續(xù)的可用性會產(chǎn)生高性能的系統(tǒng),在某些情況下可能值得付出代價。
結(jié)論
如果你正在創(chuàng)建基于微服務(wù)的分布式項目,了解CAP定理可以幫助你選擇合適的數(shù)據(jù)庫。例如,如果你可以接受最終一致性(而不是嚴(yán)格一致性),但需要快速迭代數(shù)據(jù)模型并進(jìn)行水平擴展,那么像Cassandra或Apache CouchDB這樣的AP數(shù)據(jù)庫可能能滿足你的需求并簡化部署。
另一方面,如果你的應(yīng)用程序的成功取決于數(shù)據(jù)的可靠性,例如電子商務(wù)或支付服務(wù),那么關(guān)系型數(shù)據(jù)庫如PostgreSQL可能是最佳選擇。