用太極拳講分布式理論,真舒服!
倚天屠龍記中趙敏郡主攜帶一幫高手圍攻武當(dāng),武當(dāng)派掌門張三豐被暗算,傳了一套武功給張無(wú)忌用來(lái)對(duì)付趙敏的手下。這套武功就是太極拳。
張三豐:無(wú)忌,我教你的還記得多少?
張無(wú)忌:我全忘了!
張三豐:很好,你只要記住把玄冥二老打趴下就可以了。
上篇用三國(guó)殺講分布式中的拜占庭將軍問(wèn)題,還挺有意思的,這次我們用倚天屠龍記中的太極拳來(lái)聊下剩下的三大理論:
- CAP 理論
- ACID 理論
- BASE 理論
太極拳的精髓:以柔克剛,剛?cè)岵⑦M(jìn),四兩撥千斤,無(wú)招勝有招。
我把 CAP 理論稱作太極,ACID 理論稱為陽(yáng)或剛,BASE 理論稱為陰或柔。ACID 理論追求一致性,BASE 理論本來(lái)就叫做柔性事務(wù),追求的是可用性。那張無(wú)忌為什么會(huì)全忘了還打敗了玄冥二老呢?因?yàn)樘珮O拳的精髓是拳意,無(wú)招勝有招。
1、太極的兩面
CAP 理論是對(duì)分布式系統(tǒng)的特性做了一個(gè)高度的抽象,變成了三大指標(biāo):
- 一致性(Consistency)
- 可用性(Availability)
- 分區(qū)容錯(cuò)性(Partition Tolerance)
分布式中的一致性,我們可以理解為客戶端的每次讀操作,不管訪問(wèn)的是哪個(gè)幾點(diǎn),要么讀到的都是同一份最新寫入的數(shù)據(jù),要么讀取失敗。這就很剛了,不能說(shuō)這種剛不好,在很多場(chǎng)景中,也確實(shí)需要保證高度的一致性。
為了幫助大家理解一致性,我舉個(gè)倚天屠龍記的故事:六大派圍攻光明頂。
峨眉派滅絕師太作為統(tǒng)領(lǐng),帶領(lǐng)江湖六大派圍攻光明頂,最開始的進(jìn)攻策略是從北邊進(jìn)攻。滅絕師太發(fā)現(xiàn)從北邊進(jìn)攻不妙,于是飛鴿傳書給武當(dāng)派和少林派從南邊進(jìn)攻的命令,但是少林派的飛鴿被明教輕功絕頂?shù)那嘁眚鹜蹴f一笑截獲了,最后的結(jié)果是少林派從北邊進(jìn)攻,武當(dāng)派從南邊進(jìn)攻,這不就亂套了嗎?如下圖所示:
圍攻光明頂
1.1 理解分布式中的 CAP
CAP 放到分布式系統(tǒng)中該如何理解呢?下面舉個(gè)例子幫助大家理解。
初始環(huán)境:客戶端查詢或更新節(jié)點(diǎn) 1 和 節(jié)點(diǎn) 2,兩個(gè)節(jié)點(diǎn)存的值 A = 1。
初始環(huán)境
客戶端更新節(jié)點(diǎn) 1 中 A 的值,設(shè)置 A = 5。
客戶端更新節(jié)點(diǎn) 1
節(jié)點(diǎn) 1 將 A 的值更新為 5 后,返回更新成功給客戶端。
節(jié)點(diǎn) 1 返回更新成功
客戶端訪問(wèn)到了節(jié)點(diǎn) 2 ,請(qǐng)求獲取 A 的值,結(jié)果返回 A = 1。這和節(jié)點(diǎn) 1 中存儲(chǔ)的 A 的值就不一致了。
客戶端訪問(wèn)到節(jié)點(diǎn) 2
那么怎么保證兩個(gè)節(jié)點(diǎn)中的值都是 A = 5 呢?客戶端將節(jié)點(diǎn) 1 更新后,節(jié)點(diǎn) 2 也需要更新,才能告訴客戶端更新成功了。
節(jié)點(diǎn) 2 也需要更新
兩個(gè)節(jié)點(diǎn)都更新成功后,客戶端訪問(wèn)其中任意一個(gè)節(jié)點(diǎn)獲取到的都是 A = 5。這個(gè)就叫做一致性。
兩個(gè)節(jié)點(diǎn)都更新后
一致性強(qiáng)調(diào)的是數(shù)據(jù)正確,每次讀取節(jié)點(diǎn)中的數(shù)據(jù)都是最新寫入的數(shù)據(jù)。這個(gè)我稱作剛。
但是我們生產(chǎn)的集群環(huán)境下如果發(fā)生分區(qū)故障時(shí)(節(jié)點(diǎn)失聯(lián),節(jié)點(diǎn)無(wú)法響應(yīng),節(jié)點(diǎn)無(wú)法寫入數(shù)據(jù)),客戶端查詢節(jié)點(diǎn)時(shí),我們不能返回錯(cuò)誤信息給客戶端。比如說(shuō)業(yè)務(wù)集群中的一些關(guān)鍵系統(tǒng),如注冊(cè)中心,不能因?yàn)槟硞€(gè)節(jié)點(diǎn)失聯(lián)了,就不響應(yīng)最新的數(shù)據(jù)。那么相關(guān)的業(yè)務(wù)也獲取不到正確的注冊(cè)信息而導(dǎo)致系統(tǒng)癱瘓。
可用性就派上用場(chǎng)了,犧牲數(shù)據(jù)準(zhǔn)確性,每個(gè)節(jié)點(diǎn)使用本地?cái)?shù)據(jù)來(lái)響應(yīng)客戶端的請(qǐng)求。另外當(dāng)節(jié)點(diǎn)不可用時(shí),可以使用快速失敗策略,至少不能讓服務(wù)長(zhǎng)時(shí)間不能響應(yīng)??捎眯詮?qiáng)調(diào)的是服務(wù)可用,不保證數(shù)據(jù)正確。這個(gè)我稱作柔。
如下圖所示:節(jié)點(diǎn) 1 和節(jié)點(diǎn) 2 返回給客戶端的值分別是 A = 5 和 A = 1,也就是節(jié)點(diǎn) 1 和 節(jié)點(diǎn) 2 并沒(méi)有保證數(shù)據(jù)一致性,而是考慮了節(jié)點(diǎn)的可用性。
數(shù)據(jù)不一致
分區(qū)容錯(cuò)性的含義就是節(jié)點(diǎn)間出現(xiàn)任意數(shù)量的消息丟失或高延遲的時(shí)候,系統(tǒng)仍然在繼續(xù)工作。分布式系統(tǒng)告訴客戶端,我的內(nèi)部不論出現(xiàn)什么樣的數(shù)據(jù)同步問(wèn)題,我會(huì)一直運(yùn)行。強(qiáng)調(diào)的是集群堆分區(qū)故障的容錯(cuò)能力。
1.2 CAP 三角
那么這三個(gè)指標(biāo)又有什么關(guān)系呢?這個(gè)就是我們經(jīng)常聽(tīng)到的 CAP 理論。C 代表一致性(Consistency),A 代表可用性(Availability)、P 代表分區(qū)容錯(cuò)性(Partition Tolerance)。
對(duì)于分布式系統(tǒng),CAP 三個(gè)指標(biāo)只能選擇其中兩個(gè)。
CA:保證一致性和可用性。當(dāng)分布式系統(tǒng)正常運(yùn)行時(shí)(大部分時(shí)候所處的狀態(tài)),這個(gè)時(shí)候不需要 P,那么 C 和 A 能夠同時(shí)保證。只有在發(fā)生分區(qū)故障時(shí),才需要 P,這個(gè)時(shí)候就只能在 C 和 A 之間做出選擇。典型應(yīng)用:?jiǎn)螜C(jī)版部署的 MySQL。
CP:保證數(shù)據(jù)的一致性和分區(qū)容錯(cuò)性,比如配置信息,必須保證每個(gè)節(jié)點(diǎn)存的都是最新的,正確的數(shù)據(jù)。比如 Raft 的強(qiáng)一致性系統(tǒng),會(huì)導(dǎo)致無(wú)法執(zhí)行讀操作和寫操作。典型應(yīng)用:Etcd、Consul、Hbase。
AP:保證分布式系統(tǒng)的可用性和分區(qū)容錯(cuò)性。用戶訪問(wèn)系統(tǒng),都能得到相應(yīng)數(shù)據(jù),不會(huì)出現(xiàn)響應(yīng)錯(cuò)誤,但是可能會(huì)讀到舊的數(shù)據(jù)。典型應(yīng)用:Cassandra 和 DynamoDB。
2、太極的剛
2.1 ACID 的剛
最開始知道 ACID 是研究 SQL 數(shù)據(jù)庫(kù)的時(shí)候,原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
這四個(gè)屬性是針對(duì)事務(wù)而言的,而事務(wù)就是為單個(gè)工作單元而執(zhí)行的一系列操作。如查詢、修改數(shù)據(jù)、修改數(shù)據(jù)定義。
事務(wù)不僅僅只用在數(shù)據(jù)庫(kù)上,還可以用在業(yè)務(wù)系統(tǒng)中,比如發(fā)券后扣減庫(kù)存,這種業(yè)務(wù)場(chǎng)景可以定義為一個(gè)事務(wù)。單機(jī)場(chǎng)景我們可以通過(guò)加鎖、時(shí)間序列等機(jī)制來(lái)保證單個(gè)節(jié)點(diǎn)上的 ACID 特性,但無(wú)法保證節(jié)點(diǎn)間操作的 ACID 特性。
那么分布式系統(tǒng)下該如何解決事務(wù)問(wèn)題呢?這也是面試中經(jīng)常遇到的題。分布式事務(wù)協(xié)議大家一定聽(tīng)過(guò),比如二階段提交協(xié)議和 TCC 協(xié)議,下面我還是用六大派圍攻光明頂故事來(lái)講解二階段協(xié)議。
2.2 圍攻光明頂
峨眉派想?yún)R集少林派、武當(dāng)派、昆侖派明天一起進(jìn)攻光明頂。如果有一方不同意進(jìn)攻,或者進(jìn)攻時(shí)機(jī)不一致,則需要取消整個(gè)行動(dòng)計(jì)劃。少林派、武當(dāng)派、昆侖派進(jìn)攻光明頂這一組行動(dòng)可以看成是一個(gè)分布式事務(wù),要么全部執(zhí)行、要么全部不執(zhí)行。如下圖所示:
那如何幫助滅絕師太解決這個(gè)協(xié)同問(wèn)題?我們可以用二階段提交協(xié)議來(lái)說(shuō)明。
2.3 二階段提交協(xié)議
在二階段提交協(xié)議中,滅絕師太先給少林派發(fā)送進(jìn)攻的消息,少林派作為協(xié)調(diào)者的身份,由少林派聯(lián)系武當(dāng)派和昆侖派是進(jìn)攻還是撤退。
二階段就是說(shuō)有兩個(gè)階段,1.提交請(qǐng)求階段(投票階段),2.提交執(zhí)行階段(完成階段)。
階段一:提交請(qǐng)求階段:
第一步:少林派作為協(xié)調(diào)者分別給武當(dāng)派和昆侖派發(fā)送消息:“明天進(jìn)攻光明頂,可行?”
第二步:少林派、武當(dāng)派、昆侖派分別評(píng)估明天是否能進(jìn)攻光明頂,如果能,就預(yù)留時(shí)間并鎖定,不再安排其他的進(jìn)攻事項(xiàng)。
第三步:少林派得到全部的回復(fù)結(jié)果,包括少林派自己的評(píng)估結(jié)果。最后三方的結(jié)果都是可行。
如下圖所示:
階段一
階段二:提交執(zhí)行階段:
第一步:少林派統(tǒng)計(jì)自己、昆侖派和武當(dāng)派的消息,都是可以進(jìn)攻,所以可以執(zhí)行分布式事務(wù),進(jìn)攻光明頂。
第二步:少林派通知昆侖派和武當(dāng)派進(jìn)攻光明頂。
第三步:少林派、昆侖派、武當(dāng)派召集手下弟子,進(jìn)攻光明頂(執(zhí)行事務(wù))。
第四步:昆侖派、武當(dāng)派將是否已發(fā)起進(jìn)攻告訴少林派。
第五步:少林派匯總自己、昆侖派、武當(dāng)派的進(jìn)攻結(jié)果給滅絕師太。這樣滅絕師太看到的就是統(tǒng)一的作戰(zhàn)計(jì)劃。
階段二
注意:
- 可以將滅絕師太當(dāng)做客戶端。少林派、武當(dāng)派、昆侖派當(dāng)做分布式系統(tǒng)的三個(gè)節(jié)點(diǎn)。少林派作為協(xié)調(diào)者。
- 將評(píng)估是否能進(jìn)攻光明頂以及預(yù)留時(shí)間可以理解為需要操作的對(duì)象和對(duì)象狀態(tài),是否已經(jīng)準(zhǔn)備好了,能否提交新的操作。
- 發(fā)送消息、飛鴿傳書可以理解為網(wǎng)絡(luò)消息。
- 第一個(gè)階段中,每個(gè)參與者投票表決事務(wù)是放棄還是提交,一旦投票要求提交事務(wù),那么就不允許放棄事務(wù)。
- 第二個(gè)階段中,每個(gè)參與者執(zhí)行最終統(tǒng)一的決定,提交事務(wù)或者放棄事務(wù)。這個(gè)就是 ACID 的原子性。
- 第一個(gè)階段中,需要預(yù)留資源,預(yù)留期間,其他人不能操作這個(gè)資源。
2.4 二階段協(xié)議帶來(lái)的問(wèn)題
ACID 特性是 CAP 中一致性的邊界,可以稱作最強(qiáng)的一致性,如果分布式系統(tǒng)中實(shí)現(xiàn)了一致性,必然會(huì)影響到可用性。如果一個(gè)節(jié)點(diǎn)失敗,這個(gè)分布式事務(wù)的執(zhí)行都是失敗的。
絕大數(shù)場(chǎng)景中,對(duì)一致性要求沒(méi)那么高,并不需要保證強(qiáng)一致性,短暫的不一致也能接收,最后能保證數(shù)據(jù)是正確的就OK。也就是說(shuō)我們可以用最終一致性方案來(lái)保證數(shù)據(jù)的一致性。
另外要提到的就是 TCC 協(xié)議(三階段提交協(xié)議),他是針對(duì)二階段提交中的:協(xié)調(diào)者故障,參與者長(zhǎng)期鎖定資源的痛點(diǎn)而出的協(xié)議。引入了詢問(wèn)階段和超時(shí)機(jī)制,減少資源被長(zhǎng)時(shí)間鎖定。但是需要更多的消息進(jìn)行協(xié)商,增加了系統(tǒng)負(fù)載和響應(yīng)延遲,所以三階段提交協(xié)議很少被使用。
3、太極的柔
3.1 BASE 的柔
講了太極的剛,下面來(lái)講太極的柔。談到分布式事務(wù)的柔,一定會(huì)提到 BASE 理論,俗稱柔性事務(wù)。BASE 理論是 CAP 理論中 AP 的擴(kuò)展。大部分互聯(lián)網(wǎng)分布式系統(tǒng)都強(qiáng)調(diào)可用性,都會(huì)考慮引入 BASE 支持。這個(gè)理論非常非常重要,我要告訴你的是,掌握了這個(gè)理論,設(shè)計(jì)出符合自己業(yè)務(wù)的分布式架構(gòu)也會(huì)變得容易很多,而不是摸不著頭腦。
BASE 的核心:基本可用 BA(Basically Available)、軟狀態(tài) S(Soft state)、最終一致性 E(Eventually consistent)。
那為什么叫它柔性事務(wù)?其實(shí)它和 ACID 是相對(duì)的,不需要保證強(qiáng)一致性,比如一根橡皮筋被拉彎了,你放開橡皮筋后,它就會(huì)自行恢復(fù),這個(gè)就是橡皮筋柔性的一面。
3.2 BASE 和太極拳有什么關(guān)系
太極拳每一招都不是直直的打出去的,每一招都講求圓滑、畫弧線,看起來(lái)軟綿綿的,其實(shí)是柔中帶剛。每一招的最后一下都是非常剛硬的抖動(dòng)一下(這效果我用文字實(shí)在描述不出來(lái),大家去看電視吧)。這最后一下就可以看成是剛的一面,也就是最終一致性。
3.3 基本可用
怎么理解基本可用?重點(diǎn)是在這個(gè)基本,這個(gè)理論并沒(méi)有告訴我們?cè)趺炊x基本,這是一個(gè)模糊的概念。其實(shí)就是要柔到什么程度。
在分布式系統(tǒng)中,我們可以把基本可用理解為保證核心功能可用,允許損失部分功能的可用性。基本可用可以用四種方案來(lái)實(shí)現(xiàn)。
流量削峰:比如多個(gè)秒殺場(chǎng)次,某東的 8 點(diǎn)秒殺場(chǎng),12 點(diǎn)的秒殺場(chǎng)。
延遲響應(yīng):比如雙 11 期間某商城創(chuàng)建的訂單,會(huì)提示客戶訂單正在創(chuàng)建中,可能需要等個(gè)十幾秒。
體驗(yàn)降級(jí):比如某次比賽活動(dòng),有大量用戶進(jìn)活動(dòng)頁(yè)查看圖片,這個(gè)時(shí)候,大量圖片因?yàn)榫W(wǎng)絡(luò)超時(shí)而無(wú)法顯示,這個(gè)時(shí)候就可以考慮替換原有圖片,返回清晰度沒(méi)有那么高或圖片比較小的圖片。
過(guò)載保護(hù):比如我們常用的消息隊(duì)列占滿了,可以考慮丟棄后來(lái)的請(qǐng)求,或清除隊(duì)列中的一些請(qǐng)求,保護(hù)系統(tǒng)不過(guò)載,但這都需要結(jié)合自身的業(yè)務(wù)場(chǎng)景來(lái)設(shè)計(jì)。
3.4 最終一致性
最終一致性:系統(tǒng)中的所有的數(shù)據(jù)副本在經(jīng)過(guò)一段時(shí)間的同步后,最終能夠達(dá)到一個(gè)一致的狀態(tài)。最終可以理解為一個(gè)短暫的延遲。
最終一致性在非常多的互聯(lián)網(wǎng)業(yè)務(wù)中采用。但是跟錢打交道或金融系統(tǒng)會(huì)采用強(qiáng)一致性或事務(wù)。
前面提到了 ACID 的強(qiáng)一致性,而最終一致性和它是什么關(guān)系?
強(qiáng)一致性其實(shí)也是最終一致性的一種。那最終一致性怎么理解?強(qiáng)一致性可以看作不存在延遲的一致性。如果無(wú)法容忍延遲就用強(qiáng)一致性,否則就用最終一致性。
3.5 最終一致性和太極拳有什么關(guān)系
太極拳最神奇的一個(gè)地方就是卸力,當(dāng)對(duì)方使出全力攻擊你的時(shí)候,用太極的招式將對(duì)方使出的力量卸下來(lái),使對(duì)方的攻擊無(wú)效。卸力可以和我們之前講到的流量削峰對(duì)應(yīng)。另外卸完力之后,就是我們發(fā)動(dòng)攻擊的時(shí)候。
4、無(wú)招勝有招
回到文章的開頭,張三豐教給張無(wú)忌的太極拳,張無(wú)忌全忘了,還怎么能打敗玄冥二老的呢?
因?yàn)樘珮O拳重視的是拳意,而不是招式。所以張無(wú)忌領(lǐng)會(huì)了拳意,無(wú)招勝有招。
我們?cè)O(shè)計(jì)分布式系統(tǒng)的時(shí)候,也不要死記硬背三大理論,要真正懂得原理,然后才能一點(diǎn)一點(diǎn)迭代出最適合當(dāng)前業(yè)務(wù)系統(tǒng)的分布式架構(gòu)。
5、總結(jié)
- 太極拳分為陰和陽(yáng)兩方面,就如 CAP 中的 C 和 A。
- CAP 理論是分布式中基礎(chǔ)理論,有三個(gè)重要指標(biāo):一致性、可用性、分區(qū)容錯(cuò)性。
- ACID 是傳統(tǒng)數(shù)據(jù)庫(kù)的設(shè)計(jì)理念,追求強(qiáng)一致性。四個(gè)指標(biāo):原子性、一致性、隔離性、持久性。是 CAP 中 CP 的延伸。
- BASE 理論是 CAP 中一致性和可用性權(quán)衡的結(jié)果。是 CAP 中的 AP 的延伸。注重可用性和性能優(yōu)先,根據(jù)業(yè)務(wù)的場(chǎng)景特點(diǎn),實(shí)現(xiàn)彈性的基本可用,然后實(shí)現(xiàn)數(shù)據(jù)的最終一致性。
- BASE 理論在很大程度上,解決了事務(wù)性系統(tǒng)在性能、容錯(cuò)、可用性等方面的通病。
- BASE 理論在 NoSQL 中應(yīng)用廣泛,是 NoSQL 系統(tǒng)設(shè)計(jì)的事實(shí)上的理論支撐。
文中也通過(guò)六大派圍攻光明頂?shù)陌咐o大家講解了二階段提交的核心原理,相信大家一定能看懂。
本文轉(zhuǎn)載自微信公眾號(hào)「悟空聊架構(gòu)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系悟空聊架構(gòu)公眾號(hào)。