CAP 理論是分布式系統(tǒng)設(shè)計中的一個重要理論,雖然它為系統(tǒng)設(shè)計提供了非常有用的依據(jù),但是也帶來了很多誤解箕母。本文將從 CAP 誕生的背景說起苹支,然后對理論進(jìn)行解釋砾隅,最后對 CAP 在當(dāng)前背景下的一些新理解進(jìn)行分析,澄清一些對 CAP 的誤解债蜜。
CAP 理論誕生的背景
CAP 理論的是在“數(shù)據(jù)一致性 VS 可用性”的爭論中產(chǎn)生晴埂。CAP 的作者 Brewer 在 90 年代的時候就開始研究基于集群的跨區(qū)域系統(tǒng)(實(shí)質(zhì)上是早期的云計算),對于這類系統(tǒng)而言寻定,系統(tǒng)可用性是首要目標(biāo)儒洛,因此他們采用了緩存或者事后更新的方式來優(yōu)化系統(tǒng)的可用性。盡管這些方法提升了系統(tǒng)的可用性狼速,但是犧牲了系統(tǒng)數(shù)據(jù)一致性琅锻。
Brewer 在 90 年代提出了 BASE 理論(基本可用、軟狀態(tài)向胡、最終一致性)恼蓬,這在當(dāng)時還不怎么被接受。因為大家還是比較看重 ACID 的優(yōu)點(diǎn)僵芹,不愿意放棄強(qiáng)一致性处硬。因此,Brewer 提出了 CAP 理論拇派,目的就是為了開闊分布式系統(tǒng)的設(shè)計空間荷辕,通過“三選二”的公式,解放思想件豌,不要只抓著一致性不放桐腌。
理解了 CAP 誕生的背景,我們才能更加深入的理解 CAP 理論苟径,以及它帶來的啟示案站。“三選二”的觀點(diǎn)雖然幫助大家開拓了設(shè)計思路,但是也帶來了很多誤解蟆盐。下面我們會逐一分析承边,首先來看一下 CAP 理論的解釋。
CAP 理論的經(jīng)典解釋
CAP 定理是分布式系統(tǒng)設(shè)計中最基礎(chǔ)石挂,也是最為關(guān)鍵的理論博助。它指出,分布式數(shù)據(jù)存儲不可能同時滿足以下三個條件痹愚。
一致性(Consistency):每次讀取要么獲得最近寫入的數(shù)據(jù)富岳,要么獲得一個錯誤。
可用性(Availability):每次請求都能獲得一個(非錯誤)響應(yīng)拯腮,但不保證返回的是最新寫入的數(shù)據(jù)窖式。
分區(qū)容忍(Partition tolerance):盡管任意數(shù)量的消息被節(jié)點(diǎn)間的網(wǎng)絡(luò)丟失(或延遲),系統(tǒng)仍繼續(xù)運(yùn)行动壤。
CAP 定理表明萝喘,在存在網(wǎng)絡(luò)分區(qū)的情況下,一致性和可用性必須二選一琼懊。當(dāng)網(wǎng)絡(luò)發(fā)生分區(qū)(不同節(jié)點(diǎn)之間的網(wǎng)絡(luò)發(fā)生故障或者延遲較大)時阁簸,要么失去一致性(允許不同分區(qū)的數(shù)據(jù)寫入),要么失去可用性(識別到網(wǎng)絡(luò)分區(qū)時停止服務(wù))哼丈。而在沒有發(fā)生網(wǎng)絡(luò)故障時启妹,即分布式系統(tǒng)正常運(yùn)行時,一致性和可用性是可以同時被滿足的醉旦。這里需要注意的是翅溺,CAP 定理中的一致性與 ACID 數(shù)據(jù)庫事務(wù)中的一致性截然不同。ACID 的 C 指的是事務(wù)不能破壞任何數(shù)據(jù)庫規(guī)則髓抑,如鍵的唯一性。與之相比优幸,CAP 的 C 僅指單一副本這個意義上的一致性吨拍,因此只是 ACID 一致性約束的一個嚴(yán)格的子集。
CAP 理論看起來難理解网杆,其實(shí)只要抓住一個核心點(diǎn)就能推導(dǎo)出來羹饰,不用死記硬背。在出現(xiàn)網(wǎng)絡(luò)分區(qū)的時候碳却,
如果系統(tǒng)不允許寫入队秩,那么意味著降低了系統(tǒng)的可用性,但不同分區(qū)的數(shù)據(jù)能夠保持一致昼浦,即選擇了一致性馍资。
如果系統(tǒng)允許寫入,那么意味著不同分區(qū)之間的數(shù)據(jù)產(chǎn)生不一致关噪,系統(tǒng)可用性得到保障鸟蟹,即選擇可用性乌妙。
CAP 的新理解
CAP 經(jīng)常被誤解,很大程度上是因為在討論 CAP 的時候可用性和一致性的作用范圍往往都是含糊不清的建钥。如果不先定義好可用性藤韵、一致性、分區(qū)容忍在具體場景下的概念熊经,CAP 實(shí)際上反而會束縛系統(tǒng)設(shè)計的思路泽艘。首先,由于分區(qū)很少發(fā)生镐依,那么在系統(tǒng)不存在分區(qū)的情況下沒什么理由犧牲 C 或 A匹涮。其次,C 與 A 之間的取舍可以在同一系統(tǒng)內(nèi)以非常細(xì)小的粒度反復(fù)發(fā)生馋吗,而每一次的決策可能因為具體的操作焕盟,乃至因為牽涉到特定的數(shù)據(jù)或用戶而有所不同。最后宏粤,這三種性質(zhì)都可以在程度上都可以進(jìn)行度量脚翘,并不是非黑即白的有或無∩馨ィ可用性顯然是在 0% 到 100% 之間連續(xù)變化的来农,一致性分很多級別,連分區(qū)也可以細(xì)分為不同含義崇堰,如系統(tǒng)內(nèi)的不同部分對于是否存在分區(qū)可以有不一樣的認(rèn)知沃于。
什么是分區(qū)容忍
在現(xiàn)實(shí)世界中,正常情況下分布式系統(tǒng)各個節(jié)點(diǎn)之間的通信是可靠的海诲,不會出現(xiàn)消息丟失或者延遲很高的情況繁莹,但是網(wǎng)絡(luò)是不可靠的,總會偶爾出現(xiàn)消息丟失或者消息延遲很高的情況特幔,這個時候不同區(qū)域的節(jié)點(diǎn)之間在一段時間內(nèi)就會出現(xiàn)無法通信的情況咨演,也就是發(fā)生了分區(qū)。
分區(qū)容忍就是指分布式系統(tǒng)在出現(xiàn)網(wǎng)絡(luò)分區(qū)的時候蚯斯,仍然能繼續(xù)運(yùn)行薄风,對外提供服務(wù)。注意拍嵌,這里所說的仍然能夠?qū)ν馓峁┓?wù)跟可用性的要求不一樣遭赂,可用性要求的是對于任意請求都能得到響應(yīng),意味著即使出現(xiàn)網(wǎng)絡(luò)分區(qū)所有節(jié)點(diǎn)都能夠提供服務(wù)横辆。而分區(qū)容忍的重點(diǎn)在于出現(xiàn)網(wǎng)絡(luò)分區(qū)之后撇他,系統(tǒng)仍然是可用的(包括部分可用)。
舉個例子:使用 Paxos 進(jìn)行數(shù)據(jù)復(fù)制的系統(tǒng)就是典型的 CP 系統(tǒng),即使出現(xiàn)網(wǎng)絡(luò)分區(qū)逆粹,主分區(qū)也能夠提供服務(wù)募疮,所以它是分區(qū)容忍的。再舉個反例:使用 2PC 進(jìn)行數(shù)據(jù)復(fù)制的系統(tǒng)沒有分區(qū)容忍的特性僻弹,當(dāng)出現(xiàn)網(wǎng)絡(luò)分區(qū)時阿浓,整個系統(tǒng)都會阻塞。
可用性的范圍
可用性其實(shí)很直觀:每次請求都能獲得一個(非錯誤)響應(yīng)蹋绽,但不保證返回的是最新寫入的數(shù)據(jù)芭毙。換一個說法就是對于分布式系統(tǒng)中的每個節(jié)點(diǎn),都能夠?qū)ν獠空埱笞龀鲰憫?yīng)卸耘,但不要求一致性退敦。
經(jīng)常讓我們疑惑的問題是衡量系統(tǒng)可用性的標(biāo)準(zhǔn)是什么?其實(shí)關(guān)鍵點(diǎn)在于可用性的范圍蚣抗,脫離了具體場景下的可用性范圍是沒有意義的侈百。討論可用性是要有具體場景來劃分邊界的,簡單的認(rèn)為某個算法是滿足可用性要求其實(shí)并不嚴(yán)謹(jǐn)翰铡,因為在工程實(shí)現(xiàn)中會有很多的技巧去彌補(bǔ)修正钝域。
舉個例子:谷歌文檔就是非常典型的 AP 系統(tǒng),它在網(wǎng)絡(luò)斷了的情況下也能夠使用锭魔。訣竅在于它在發(fā)現(xiàn)網(wǎng)絡(luò)斷了之后會進(jìn)入離線模式例证,允許用戶繼續(xù)進(jìn)行編輯,然后在網(wǎng)絡(luò)恢復(fù)之后再對修改的內(nèi)容進(jìn)行合并處理迷捧≈郑可以發(fā)現(xiàn)對于谷歌文檔來說,用戶的瀏覽器也是它系統(tǒng)的一個節(jié)點(diǎn)漠秋,當(dāng)出現(xiàn)網(wǎng)絡(luò)分區(qū)時笙蒙,它仍然能夠為用戶提供服務(wù),但是代價是放棄了一致性庆锦,因為用戶做的修改只有本地知道捅位,服務(wù)端是不清楚的。所以在這個例子里面肥荔,可用性的范圍是包括了用戶瀏覽器在內(nèi)的,不是我們常規(guī)理解的分布式系統(tǒng)的節(jié)點(diǎn)一定就是服務(wù)端的機(jī)器朝群。
值得注意的是在現(xiàn)實(shí)世界中燕耿,我們一般不會去追求完美的可用性,所以一般的說法是高可用姜胖,即盡可能保證更多的節(jié)點(diǎn)服務(wù)可用誉帅。這也是為什么 Paxos 這類的一致性算法越來越流行的原因之一。
一致性的范圍
討論一致性的時候必須要明確一致性的范圍,即在一定的邊界內(nèi)狀態(tài)是一致的蚜锨,超出邊界之外的一致性是無從談起的档插。比如 Paxos 在發(fā)生網(wǎng)絡(luò)分區(qū)的時候,在一個主分區(qū)內(nèi)可以保證完備的一致性和可用性亚再,而在分區(qū)外服務(wù)是不可用的郭膛。值得注意的是,當(dāng)系統(tǒng)在分區(qū)的時候選擇了一致性氛悬,也就是 CP则剃,并不意味著完全失去了可用性,這取決于一致性算法的實(shí)現(xiàn)如捅。比如標(biāo)準(zhǔn)的兩階段提交發(fā)生分區(qū)的時候是完全不可用的棍现,而 Paxos 則保證了主分區(qū)的一致性和可用性旺遮。
經(jīng)過上面的討論可以發(fā)現(xiàn)渤弛,可用性的范圍要求比一致性的范圍要求要更嚴(yán)格,CAP 理論中的可用性要求的是整個系統(tǒng)的可用性茎刚,即使出現(xiàn)部分節(jié)點(diǎn)不可用也算是違反了可用性約束悲关。而一致性的要求則沒有那么高谎僻,發(fā)生網(wǎng)絡(luò)分區(qū)的時候只要保證主分區(qū)數(shù)據(jù)一致性,也認(rèn)為系統(tǒng)是符合一致性約束的坚洽。為什么這么說呢戈稿?因為當(dāng)出現(xiàn)網(wǎng)絡(luò)分區(qū)的時候,客戶端只要通過訪問主分區(qū)就能得到最新的值(訪問超過半數(shù)以上節(jié)點(diǎn)讶舰,如果值都相同說明訪問的數(shù)據(jù)是最新的)鞍盗,此時系統(tǒng)是滿足 CAP 理論中一致性的要求的。
管理分區(qū)
網(wǎng)絡(luò)分區(qū)是分布式系統(tǒng)中必然發(fā)生的事情跳昼,經(jīng)典的 CAP 理論是忽略網(wǎng)絡(luò)延遲的般甲,但是在現(xiàn)實(shí)世界中,網(wǎng)絡(luò)延遲跟分區(qū)密切相關(guān)鹅颊。也就是說當(dāng)系統(tǒng)在有限的時間內(nèi)無法通信達(dá)成一致(網(wǎng)絡(luò)延遲很高)敷存,就意味著發(fā)生了分區(qū)。此時就需要在一致性和可用性之間做出選擇:選擇繼續(xù)重試就意味著選擇一致性堪伍,放棄可用性锚烦;放棄數(shù)據(jù)一致性讓操作完成就意味著選擇了可用性。值得注意的是在分區(qū)的時候放棄數(shù)據(jù)一致性并不是意味著完全不管帝雇,一般工程實(shí)現(xiàn)會采用重試的方式達(dá)到最終一致性涮俄。
通過上面的分析可以發(fā)現(xiàn),平衡分區(qū)期間可用性和一致性的影響是分布式系統(tǒng)設(shè)計中的關(guān)鍵問題尸闸。因此彻亲,管理分區(qū)不僅是需要主動發(fā)現(xiàn)分區(qū)孕锄,還需要針對分區(qū)期間產(chǎn)生的影響準(zhǔn)備恢復(fù)過程。也就是說我們可以從另一個角度來應(yīng)用 CAP 理論:系統(tǒng)進(jìn)入分區(qū)模式的時候苞尝,如何在一致性和可用性之間做出選擇畸肆。
管理分區(qū)有三個步驟:
檢測到分區(qū)開始
明確進(jìn)入分區(qū)模式,限制某些操作
當(dāng)通信恢復(fù)后啟動分區(qū)恢復(fù)過程
當(dāng)系統(tǒng)進(jìn)入分區(qū)模式之后宙址,有兩種選擇:
選擇一致性:例如 Paxos 算法轴脐,只有大多數(shù)的主分區(qū)能夠進(jìn)行操作,其他分區(qū)不可用曼氛,當(dāng)網(wǎng)絡(luò)恢復(fù)之后少數(shù)節(jié)點(diǎn)跟多數(shù)節(jié)點(diǎn)同步數(shù)據(jù)豁辉。
選擇可用性:例如谷歌文檔,出現(xiàn)分區(qū)時進(jìn)入離線模式舀患,等網(wǎng)絡(luò)恢復(fù)了客戶端跟服務(wù)端數(shù)據(jù)進(jìn)行合并恢復(fù)徽级。
總結(jié)
理論抽象于現(xiàn)實(shí),服務(wù)于現(xiàn)實(shí)聊浅,但絕不等于現(xiàn)實(shí)餐抢。對 CAP 理論“三選二”的誤解就源于我們經(jīng)常把理論等同于現(xiàn)實(shí)。CAP 的誕生主要是為了拓寬設(shè)計思路低匙,不要局限在強(qiáng)一致性的約束中旷痕。簡單的把“三選二”進(jìn)行套用反而限制了設(shè)計思路。在現(xiàn)實(shí)世界中顽冶,不同業(yè)務(wù)場景對可用性和一致性的要求不一樣欺抗,并且一致性和可用性的范圍和區(qū)間是動態(tài)變化的,并不是非此即彼强重。因此绞呈,準(zhǔn)確理解 CAP 理論,從管理分區(qū)的角度出發(fā)间景,結(jié)合具體的業(yè)務(wù)場景佃声,才能做出更好的系統(tǒng)設(shè)計。
加java高級架構(gòu)師群獲取Java工程化倘要、高性能及分布式圾亏、高性能、深入淺出封拧。高架構(gòu)志鹃。
性能調(diào)優(yōu)、Spring泽西,MyBatis曹铃,Netty源碼分析和大數(shù)據(jù)等多個知識點(diǎn)高級進(jìn)階干貨的直播免費(fèi)學(xué)習(xí)權(quán)限
都是大牛帶飛?讓你少走很多的彎路的?群號是:?798891710對了?小白勿進(jìn)?最好是有開發(fā)經(jīng)驗