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






































