文章轉(zhuǎn)載自:https://www.hollischuang.com/archives/666
2000年7月,加州大學(xué)伯克利分校的Eric Brewer教授在ACM PODC會議上提出CAP猜想贸辈。2年后篇亭,麻省理工學(xué)院的Seth Gilbert和Nancy Lynch從理論上證明了CAP仇箱。之后梳码,CAP理論正式成為分布式計算領(lǐng)域的公認(rèn)定理裆熙。
無論你是一個系統(tǒng)架構(gòu)師枫攀,還是一個普通開發(fā)必指,當(dāng)你開發(fā)或者設(shè)計一個分布式系統(tǒng)的時候囊咏,CAP理論是無論如何也繞不過去的。本文就來介紹一下到底什么是CAP理論,如何證明CAP理論梅割,以及CAP的權(quán)衡問題霜第。
CAP理論概述
CAP理論:一個分布式系統(tǒng)最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯性(Partition tolerance)這三項中的兩項户辞。
讀者需要注意的的是泌类,CAP理論中的CA和數(shù)據(jù)庫事務(wù)中ACID的CA并完全是同一回事兒。兩者之中的A都是C都是一致性(Consistency)底燎。CAP中的A指的是可用性(Availability)刃榨,而ACID中的A指的是原子性(Atomicity),切勿混為一談双仍。
CAP的定義
Consistency 一致性
一致性指“all nodes see the same data at the same time
”枢希,即更新操作成功并返回客戶端完成后,所有節(jié)點在同一時間的數(shù)據(jù)完全一致朱沃,所以苞轿,一致性,說的就是數(shù)據(jù)一致性为流。分布式的一致性
對于一致性呕屎,可以分為從客戶端和服務(wù)端兩個不同的視角。從客戶端來看敬察,一致性主要指的是多并發(fā)訪問時更新過的數(shù)據(jù)如何獲取的問題秀睛。從服務(wù)端來看,則是更新如何復(fù)制分布到整個系統(tǒng)莲祸,以保證數(shù)據(jù)最終一致蹂安。
一致性是因為有并發(fā)讀寫才有的問題,因此在理解一致性的問題時锐帜,一定要注意結(jié)合考慮并發(fā)讀寫的場景田盈。
從客戶端角度,多進(jìn)程并發(fā)訪問時缴阎,更新過的數(shù)據(jù)在不同進(jìn)程如何獲取的不同策略允瞧,決定了不同的一致性。
三種一致性策略
對于關(guān)系型數(shù)據(jù)庫蛮拔,要求更新過的數(shù)據(jù)能被后續(xù)的訪問都能看到述暂,這是強(qiáng)一致性。
如果能容忍后續(xù)的部分或者全部訪問不到建炫,則是弱一致性畦韭。
如果經(jīng)過一段時間后要求能訪問到更新后的數(shù)據(jù),則是最終一致性肛跌。
CAP中說艺配,不可能同時滿足的這個一致性指的是強(qiáng)一致性察郁。
Availability 可用性
可用性指“Reads and writes always succeed
”,即服務(wù)一直可用转唉,而且是正常響應(yīng)時間皮钠。
對于一個可用性的分布式系統(tǒng),每一個非故障的節(jié)點必須對每一個請求作出響應(yīng)酝掩。所以鳞芙,一般我們在衡量一個系統(tǒng)的可用性的時候,都是通過停機(jī)時間來計算的期虾。
可用性分類 | 可用水平(%) | 年可容忍停機(jī)時間 |
---|---|---|
容錯可用性 | 99.9999 | <1 min |
極高可用性 | 99.999 | <5 min |
具有故障自動恢復(fù)能力的可用性 | 99.99 | <53 min |
高可用性 | 99.9 | <8.8h |
商品可用性 | 99 | <43.8 min |
通常我們描述一個系統(tǒng)的可用性時,我們說淘寶的系統(tǒng)可用性可以達(dá)到5個9驯嘱,意思就是說他的可用水平是99.999%镶苞,即全年停機(jī)時間不超過 (1-0.99999)*365*24*60 = 5.256 min
,這是一個極高的要求鞠评。
好的可用性主要是指系統(tǒng)能夠很好的為用戶服務(wù)茂蚓,不出現(xiàn)用戶操作失敗或者訪問超時等用戶體驗不好的情況。一個分布式系統(tǒng)剃幌,上下游設(shè)計很多系統(tǒng)如負(fù)載均衡聋涨、WEB服務(wù)器、應(yīng)用代碼负乡、數(shù)據(jù)庫服務(wù)器等牍白,任何一個節(jié)點的不穩(wěn)定都可以影響可用性。
Partition Tolerance分區(qū)容錯性
分區(qū)容錯性指“the system continues to operate despite arbitrary message loss or failure of part of the system
”抖棘,即分布式系統(tǒng)在遇到某節(jié)點或網(wǎng)絡(luò)分區(qū)故障的時候茂腥,仍然能夠?qū)ν馓峁M足一致性和可用性的服務(wù)。
分區(qū)容錯性和擴(kuò)展性緊密相關(guān)切省。在分布式應(yīng)用中最岗,可能因為一些分布式的原因?qū)е孪到y(tǒng)無法正常運(yùn)轉(zhuǎn)。好的分區(qū)容錯性要求能夠使應(yīng)用雖然是一個分布式系統(tǒng)朝捆,而看上去卻好像是在一個可以運(yùn)轉(zhuǎn)正常的整體般渡。比如現(xiàn)在的分布式系統(tǒng)中有某一個或者幾個機(jī)器宕掉了,其他剩下的機(jī)器還能夠正常運(yùn)轉(zhuǎn)滿足系統(tǒng)需求芙盘,或者是機(jī)器之間有網(wǎng)絡(luò)異常驯用,將分布式系統(tǒng)分隔未獨立的幾個部分,各個部分還能維持分布式系統(tǒng)的運(yùn)作何陆,這樣就具有好的分區(qū)容錯性晨汹。
簡單點說,就是在網(wǎng)絡(luò)中斷贷盲,消息丟失的情況下淘这,系統(tǒng)如果還能正常工作剥扣,就是有比較好的分區(qū)容錯性。
CAP的證明
如上圖铝穷,是我們證明CAP的基本場景钠怯,網(wǎng)絡(luò)中有兩個節(jié)點N1和N2,可以簡單的理解N1和N2分別是兩臺計算機(jī)曙聂,他們之間網(wǎng)絡(luò)可以連通晦炊,N1中有一個應(yīng)用程序A,和一個數(shù)據(jù)庫V宁脊,N2也有一個應(yīng)用程序B2和一個數(shù)據(jù)庫V《瞎現(xiàn)在,A和B是分布式系統(tǒng)的兩個部分榆苞,V是分布式系統(tǒng)的數(shù)據(jù)存儲的兩個子數(shù)據(jù)庫稳衬。
在滿足一致性的時候,N1和N2中的數(shù)據(jù)是一樣的坐漏,V0=V0薄疚。在滿足可用性的時候,用戶不管是請求N1或者N2赊琳,都會得到立即響應(yīng)街夭。在滿足分區(qū)容錯性的情況下,N1和N2有任何一方宕機(jī)躏筏,或者網(wǎng)絡(luò)不通的時候板丽,都不會影響N1和N2彼此之間的正常運(yùn)作。
如上圖寸士,是分布式系統(tǒng)正常運(yùn)轉(zhuǎn)的流程檐什,用戶向N1機(jī)器請求數(shù)據(jù)更新,程序A更新數(shù)據(jù)庫Vo為V1弱卡,分布式系統(tǒng)將數(shù)據(jù)進(jìn)行同步操作M乃正,將V1同步的N2中V0,使得N2中的數(shù)據(jù)V0也更新為V1婶博,N2中的數(shù)據(jù)再響應(yīng)N2的請求瓮具。
這里,可以定義N1和N2的數(shù)據(jù)庫V之間的數(shù)據(jù)是否一樣為一致性凡人;外部對N1和N2的請求響應(yīng)為可用行名党;N1和N2之間的網(wǎng)絡(luò)環(huán)境為分區(qū)容錯性。這是正常運(yùn)作的場景挠轴,也是理想的場景传睹,然而現(xiàn)實是殘酷的,當(dāng)錯誤發(fā)生的時候岸晦,一致性和可用性還有分區(qū)容錯性欧啤,是否能同時滿足睛藻,還是說要進(jìn)行取舍呢?
作為一個分布式系統(tǒng)邢隧,它和單機(jī)系統(tǒng)的最大區(qū)別店印,就在于網(wǎng)絡(luò),現(xiàn)在假設(shè)一種極端情況倒慧,N1和N2之間的網(wǎng)絡(luò)斷開了按摘,我們要支持這種網(wǎng)絡(luò)異常,相當(dāng)于要滿足分區(qū)容錯性纫谅,能不能同時滿足一致性和響應(yīng)性呢炫贤?還是說要對他們進(jìn)行取舍。
假設(shè)在N1和N2之間網(wǎng)絡(luò)斷開的時候系宜,有用戶向N1發(fā)送數(shù)據(jù)更新請求照激,那N1中的數(shù)據(jù)V0將被更新為V1,由于網(wǎng)絡(luò)是斷開的盹牧,所以分布式系統(tǒng)同步操作M,所以N2中的數(shù)據(jù)依舊是V0励幼;這個時候汰寓,有用戶向N2發(fā)送數(shù)據(jù)讀取請求,由于數(shù)據(jù)還沒有進(jìn)行同步苹粟,應(yīng)用程序沒辦法立即給用戶返回最新的數(shù)據(jù)V1有滑,怎么辦呢?
有二種選擇嵌削,第一毛好,犧牲數(shù)據(jù)一致性,保證可用性苛秕。響應(yīng)舊的數(shù)據(jù)V0給用戶肌访;
第二,犧牲可用性艇劫,保證數(shù)據(jù)一致性吼驶。阻塞等待,直到網(wǎng)絡(luò)連接恢復(fù)店煞,數(shù)據(jù)更新操作M完成之后蟹演,再給用戶響應(yīng)最新的數(shù)據(jù)V1。
這個過程顷蟀,證明了要滿足分區(qū)容錯性的分布式系統(tǒng)酒请,只能在一致性和可用性兩者中,選擇其中一個鸣个。
CAP權(quán)衡
通過CAP理論及前面的證明羞反,我們知道無法同時滿足一致性布朦、可用性和分區(qū)容錯性這三個特性,那要舍棄哪個呢苟弛?
我們分三種情況來闡述一下喝滞。
CA without P
這種情況在分布式系統(tǒng)中幾乎是不存在的。首先在分布式環(huán)境下膏秫,網(wǎng)絡(luò)分區(qū)是一個自然的事實右遭。因為分區(qū)是必然的,所以如果舍棄P缤削,意味著要舍棄分布式系統(tǒng)窘哈。那也就沒有必要再討論CAP理論了。這也是為什么在前面的CAP證明中亭敢,我們以系統(tǒng)滿足P為前提論述了無法同時滿足C和A滚婉。
比如我們熟知的關(guān)系型數(shù)據(jù)庫,如My Sql和Oracle就是保證了可用性和數(shù)據(jù)一致性帅刀,但是他并不是個分布式系統(tǒng)让腹。一旦關(guān)系型數(shù)據(jù)庫要考慮主備同步、集群部署等就必須要把P也考慮進(jìn)來扣溺。
其實骇窍,在CAP理論中。C锥余,A腹纳,P三者并不是平等的,CAP之父在《Spanner驱犹,真時嘲恍,CAP理論》一文中寫到:
如果說Spanner真有什么特別之處,那就是谷歌的廣域網(wǎng)雄驹。Google通過建立私有網(wǎng)絡(luò)以及強(qiáng)大的網(wǎng)絡(luò)工程能力來保證P佃牛,在多年運(yùn)營改進(jìn)的基礎(chǔ)上,在生產(chǎn)環(huán)境中可以最大程度的減少分區(qū)發(fā)生荠医,從而實現(xiàn)高可用性吁脱。
從Google的經(jīng)驗中可以得到的結(jié)論是,無法通過降低CA來提升P彬向。要想提升系統(tǒng)的分區(qū)容錯性兼贡,需要通過提升基礎(chǔ)設(shè)施的穩(wěn)定性來保障。
所以娃胆,對于一個分布式系統(tǒng)來說遍希。P是一個基本要求,CAP三者中里烦,只能在CA兩者之間做權(quán)衡凿蒜,并且要想盡辦法提升P禁谦。
CP without A
如果一個分布式系統(tǒng)不要求強(qiáng)的可用性,即容許系統(tǒng)停機(jī)或者長時間無響應(yīng)的話废封,就可以在CAP三者中保障CP而舍棄A州泊。
一個保證了CP而一個舍棄了A的分布式系統(tǒng),一旦發(fā)生網(wǎng)絡(luò)故障或者消息丟失等情況漂洋,就要犧牲用戶的體驗遥皂,等待所有數(shù)據(jù)全部一致了之后再讓用戶訪問系統(tǒng)。
設(shè)計成CP的系統(tǒng)其實也不少刽漂,其中最典型的就是很多分布式數(shù)據(jù)庫演训,他們都是設(shè)計成CP的。在發(fā)生極端情況時贝咙,優(yōu)先保證數(shù)據(jù)的強(qiáng)一致性样悟,代價就是舍棄系統(tǒng)的可用性。如Redis庭猩、HBase等窟她,還有分布式系統(tǒng)中常用的Zookeeper也是在CAP三者之中選擇優(yōu)先保證CP的。
無論是像Redis蔼水、HBase這種分布式存儲系統(tǒng)礁苗,還是像Zookeeper這種分布式協(xié)調(diào)組件。數(shù)據(jù)的一致性是他們最最基本的要求徙缴。一個連數(shù)據(jù)一致性都保證不了的分布式存儲要他有何用?
在我的Zookeeper介紹(二)——Zookeeper概述一文中其實介紹過zk關(guān)于CAP的思考嘁信,這里再簡單回顧一下:
ZooKeeper是個CP(一致性+分區(qū)容錯性)的于样,即任何時刻對ZooKeeper的訪問請求能得到一致的數(shù)據(jù)結(jié)果,同時系統(tǒng)對網(wǎng)絡(luò)分割具備容錯性潘靖。但是它不能保證每次服務(wù)請求的可用性穿剖,也就是在極端環(huán)境下,ZooKeeper可能會丟棄一些請求卦溢,消費者程序需要重新請求才能獲得結(jié)果糊余。ZooKeeper是分布式協(xié)調(diào)服務(wù),它的職責(zé)是保證數(shù)據(jù)在其管轄下的所有服務(wù)之間保持同步单寂、一致贬芥。所以就不難理解為什么ZooKeeper被設(shè)計成CP而不是AP特性的了。
AP wihtout C
要高可用并允許分區(qū)宣决,則需放棄一致性蘸劈。一旦網(wǎng)絡(luò)問題發(fā)生,節(jié)點之間可能會失去聯(lián)系尊沸。為了保證高可用威沫,需要在用戶訪問時可以馬上得到返回贤惯,則每個節(jié)點只能用本地數(shù)據(jù)提供服務(wù),而這樣會導(dǎo)致全局?jǐn)?shù)據(jù)的不一致性棒掠。
這種舍棄強(qiáng)一致性而保證系統(tǒng)的分區(qū)容錯性和可用性的場景和案例非常多孵构。前面我們介紹可用性的時候說到過,很多系統(tǒng)在可用性方面會做很多事情來保證系統(tǒng)的全年可用性可以達(dá)到N個9烟很,所以颈墅,對于很多業(yè)務(wù)系統(tǒng)來說,比如淘寶的購物溯职,12306的買票精盅。都是在可用性和一致性之間舍棄了一致性而選擇可用性。
你在12306買票的時候肯定遇到過這種場景谜酒,當(dāng)你購買的時候提示你是有票的(但是可能實際已經(jīng)沒票了)叹俏,你也正常的去輸入驗證碼,下單了僻族。但是過了一會系統(tǒng)提示你下單失敗粘驰,余票不足。這其實就是先在可用性方面保證系統(tǒng)可以正常的服務(wù)述么,然后在數(shù)據(jù)的一致性方面做了些犧牲蝌数,會影響一些用戶體驗,但是也不至于造成用戶流程的嚴(yán)重阻塞度秘。
但是顶伞,我們說很多網(wǎng)站犧牲了一致性,選擇了可用性剑梳,這其實也不準(zhǔn)確的唆貌。就比如上面的買票的例子,其實舍棄的只是強(qiáng)一致性垢乙。退而求其次保證了最終一致性锨咙。也就是說,雖然下單的瞬間追逮,關(guān)于車票的庫存可能存在數(shù)據(jù)不一致的情況酪刀,但是過了一段時間,還是要保證最終一致性的钮孵。
對于多數(shù)大型互聯(lián)網(wǎng)應(yīng)用的場景骂倘,主機(jī)眾多、部署分散油猫,而且現(xiàn)在的集群規(guī)模越來越大稠茂,所以節(jié)點故障、網(wǎng)絡(luò)故障是常態(tài),而且要保證服務(wù)可用性達(dá)到N個9睬关,即保證P和A诱担,舍棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗电爹,但沒達(dá)到造成用戶流程的嚴(yán)重程度蔫仙。
適合的才是最好的
上面介紹了如何CAP中權(quán)衡及取舍以及典型的案例。孰優(yōu)孰略丐箩,沒有定論摇邦,只能根據(jù)場景定奪,適合的才是最好的屎勘。
對于涉及到錢財這樣不能有一絲讓步的場景施籍,C必須保證。網(wǎng)絡(luò)發(fā)生故障寧可停止服務(wù)概漱,這是保證CP丑慎,舍棄A。比如前幾年支付寶光纜被挖斷的事件瓤摧,在網(wǎng)絡(luò)出現(xiàn)故障的時候竿裂,支付寶就在可用性和數(shù)據(jù)一致性之間選擇了數(shù)據(jù)一致性,用戶感受到的是支付寶系統(tǒng)長時間宕機(jī)照弥,但是其實背后是無數(shù)的工程師在恢復(fù)數(shù)據(jù)腻异,保證數(shù)數(shù)據(jù)的一致性。
對于其他場景这揣,比較普遍的做法是選擇可用性和分區(qū)容錯性悔常,舍棄強(qiáng)一致性,退而求其次使用最終一致性來保證數(shù)據(jù)的安全给赞。這其實是分布式領(lǐng)域的另外一個理論——BASE理論这嚣。我們下一篇文章再來介紹。
總結(jié)
無論你是一個架構(gòu)師塞俱,還是一個普通開發(fā),在設(shè)計或開發(fā)分布式系統(tǒng)的時候吏垮,不可避免的要在CAP中做權(quán)衡障涯。需要根據(jù)自己的系統(tǒng)的實際情況,選擇最適合自己的方案膳汪。
參考資料:
一文帶你重新審視CAP理論與分布式系統(tǒng)設(shè)計