您好,登錄后才能下訂單哦!
這次準(zhǔn)備開啟一個(gè)新的系列來寫了,聊聊分布式系統(tǒng)中的關(guān)注點(diǎn)。節(jié)奏不會(huì)排的太緊湊,計(jì)劃兩周一更吧。
本文是本系列的第三篇。與前兩篇《不知道是不是最通俗易懂的《數(shù)據(jù)一致性》剖析了》、《煩人的數(shù)據(jù)不一致到底怎么解決?——通過“共識(shí)”達(dá)成數(shù)據(jù)一致性》形成完整的「數(shù)據(jù)一致性」合集。
一、為什么需要事務(wù)
如果說「共識(shí)」解決的是「水平」問題,那么「事務(wù)」解決的是「垂直」問題。是如何讓一條繩上的螞蚱共同起舞?
事務(wù)只是一個(gè)計(jì)算機(jī)術(shù)語,而事務(wù)的體現(xiàn)形式其實(shí)在我們生活中也無處不在。任何我們認(rèn)為應(yīng)該是這樣的事情,去確保它達(dá)到預(yù)期的過程就是「事務(wù)」。 往小了說,我們平時(shí)在走路的時(shí)候,向前擺動(dòng)左手的同時(shí)抬右腿,如果不是這樣的話就是不一致,別人會(huì)說你走路不協(xié)調(diào)。所以我們小時(shí)候父母會(huì)通過各種方式教會(huì)我們這個(gè),這些各式各樣的方式就好比我們?cè)谲浖_發(fā)中去實(shí)施「事務(wù)」一樣,一題是多解的。
二、事務(wù)的來源
提到事務(wù)不得不提到「XA規(guī)范」[1],這是分布式還沒大行其道的時(shí)期,被大多數(shù)的數(shù)據(jù)庫作為其內(nèi)部分布式事務(wù)實(shí)現(xiàn)的接口標(biāo)準(zhǔn)。
▲圖片來源于論文中,版權(quán)歸原作者所有
「XA規(guī)范」就是上圖中「RM」和「TM」的交互規(guī)范和接口定義。僅僅是定義了xa_和ax_系列的函數(shù)原型以及功能描述、約束和實(shí)施規(guī)范等,并不包括建議的實(shí)現(xiàn)方式。后面會(huì)提到的兩階段提交(2PC)是「TM」協(xié)調(diào)「RM」們完成事務(wù)的方法。
所以其實(shí)可以說,事務(wù)起源于數(shù)據(jù)庫,輝煌于分布式系統(tǒng)。在摩爾定律還適用的時(shí)候,軟件系統(tǒng)為了承載更大的流量或者說用戶數(shù),開始運(yùn)用「分治」的思想來設(shè)計(jì)。然后隨著互聯(lián)網(wǎng)的蓬勃發(fā)展,B/S應(yīng)用大行其道的背景下,分布式系統(tǒng)越來越常見。并且隨著一個(gè)個(gè)巨無霸互聯(lián)網(wǎng)公司的出現(xiàn),越來越被鼓吹和傳頌。
一輪明月的背后是一個(gè)陰暗面,從來不讓人看見。
能被吹捧的永遠(yuǎn)是有益的一面,再加上耀眼的數(shù)據(jù):多少TPS、多少Q(mào)PS,更抓人眼球。但是這背后為了讓「分治」后的系統(tǒng)能夠盡可能的像單個(gè)個(gè)體一樣運(yùn)作,各類專家學(xué)者們通過多年研究,才有了如今的各種著名理論和解決方案。
三、分布式系統(tǒng)中的事務(wù)問題
正如前面所說,事務(wù)問題其實(shí)一直存在,只是在分布式系統(tǒng)中被放大了。并且隨著系統(tǒng)拆分的粒度越細(xì),問題的復(fù)雜度成指數(shù)上升。
分布式系統(tǒng)的事務(wù),不得不提到被廣為流傳的兩個(gè)理論:「CAP」、「BASE」。
「CAP」理論由Eric Brewer在2000年P(guān)ODC會(huì)議上提出[2],所以還被稱為Brewer定理。是Eric Brewer在Inktomi期間研發(fā)搜索引擎、分布式web緩存時(shí)得出的一個(gè)猜想:
It is impossible for a web service to provide the three following guarantees : Consistency, Availability and Partition-tolerance.
后來Seth Gilbert和Nancy Lynch對(duì)其進(jìn)行了證明[3],成為我們熟知的「CAP」定理(感謝園友@bangerlee的信息收集)。
對(duì),就是下面這張經(jīng)典的圖。
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有
一致性(consistency):這里的一致性指是「線性一致性」。(關(guān)于線性一致性的解釋,點(diǎn)我可閱讀)
可用性(availability):每個(gè)請(qǐng)求都在一定時(shí)限內(nèi)得到響應(yīng)。
分區(qū)容忍性(partition-tolerance):這應(yīng)該是這三點(diǎn)中最晦澀的。允許丟失以一個(gè)節(jié)點(diǎn)發(fā)給另一個(gè)節(jié)點(diǎn)的任意多的消息。只要是分布式系統(tǒng),這項(xiàng)是無法逃避的,因?yàn)榫W(wǎng)絡(luò)、硬件說不準(zhǔn)啥時(shí)候就出問題了。
舉個(gè)不是特別嚴(yán)謹(jǐn)?shù)睦樱@就好比要實(shí)現(xiàn)一個(gè)系統(tǒng)不能產(chǎn)生BUG(C),并且10天內(nèi)完成上線(A),以及需要多人團(tuán)隊(duì)一起協(xié)作進(jìn)行(P)。我們做開發(fā)的也很清楚這三者是無法兼得的。況且只要是一個(gè)組織,團(tuán)隊(duì)協(xié)作是無法避免的,正如這里的分區(qū)容忍性一樣,比如得考慮人員請(qǐng)假的問題。剩下的2項(xiàng),如果說可以達(dá)到?jīng)]有BUG的話,那就是時(shí)間無限延長,但也只是無限趨近于0,并不能達(dá)到真正的0,因?yàn)闆]有人可以保證發(fā)現(xiàn)了所有的BUG。
「BASE」理論是由時(shí)任ebay架構(gòu)師的Dan Pritchett提出的[4],本質(zhì)上就是對(duì)「線性一致性」的弱化。弱化的方式正如本集合的第一篇文章中所提到的「順序一致性」和「最終一致性」。(關(guān)于這兩種一致性的解釋,點(diǎn)我可閱讀)
「BASE」理論解釋如下:
基本可用(Basically Available)。分布式系統(tǒng)在出現(xiàn)故障時(shí),允許損失部分可用功能,保證核心功能可用。
軟狀態(tài)(Soft State)。狀態(tài)可以有一段時(shí)間不同步,且這個(gè)狀態(tài)不影響系統(tǒng)可用性。
最終一致(Eventually Consistent)。確保最終數(shù)據(jù)能夠一致,而不是時(shí)時(shí)保持強(qiáng)一致。
「BASE」理論的提出并不是取代「CAP」理論,讓我們?cè)趯?shí)際的工作中就可以完全的撇開「線性一致性」。并不是這樣,而是引導(dǎo)我們可以區(qū)分核心和非核心,然后分別對(duì)待,核心部分還是需要用CAP理論來保證「線性一致性」。為什么要區(qū)別對(duì)待?根本上還是無法容忍「線性一致性」帶來的巨大的性能損耗,因?yàn)樗欠纯缮炜s性的。但是只要涉及到Money之類的高敏感數(shù)據(jù)的操作部分,還是必須保證「線性一致性」。
還是上面的例子,我們側(cè)重于降低核心功能的BUG,不花過多精力在非核心功能上(BA)。我們?cè)试S產(chǎn)生不影響核心功能的BUG(S),但是必須最終要修復(fù)(E)。
四、分布式事務(wù)的解決方案
如果說「CAP」理論和「BASE」理論是「道」,那么圍繞這兩個(gè)理論演化的解決方案就是「術(shù)」。對(duì)我們來說,在實(shí)際的運(yùn)用中根據(jù)所處的場景找到最合適的,是我們最重要的事。
以「CAP」為基礎(chǔ)的強(qiáng)一致性解決方案都會(huì)引入一個(gè)類似“協(xié)調(diào)器”的東西來作為全局事務(wù)的掌控者,可以來看一下。
01 兩階段提交(2PC)[5]
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有
印象中左耳朵耗子(陳皓)之前拿西方結(jié)婚時(shí)的儀式做過一個(gè)形象的比喻。大致好像是牧師分別詢問男女雙方“你愿意嗎?”相當(dāng)于這里的「請(qǐng)求提交」,得到的“yes”相當(dāng)于「是」這個(gè)答復(fù)。然后再要求給對(duì)方帶上戒指,這個(gè)要求就相當(dāng)于這里的「提交」,帶完戒指之后的反饋就是「ACK」。
另外值得注意的是,參與者在答復(fù)「是」之前會(huì)將自己的內(nèi)部資源變?yōu)樽枞麪顟B(tài)。因此如果在產(chǎn)生阻塞后協(xié)調(diào)者出問題,那么這些被阻塞的資源有可能就一直不被釋放了,需要額外的介入。
2PC相對(duì)來說是最簡單的事務(wù)模型,但缺點(diǎn)也更多。其它缺點(diǎn)諸如:在某些場景下的數(shù)據(jù)不一致(參與者與協(xié)調(diào)者共同與「提交」環(huán)節(jié)掛了)、阻塞范圍過大等問題。
02 三階段提交(3PC)[6]
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有
3PC的出現(xiàn)就是通過增加復(fù)雜度(性能也因此降低)來解決或優(yōu)化2PC中的一部分問題。本質(zhì)的變化就是在2PC的「請(qǐng)求提交」之后增加了一個(gè)「準(zhǔn)備提交」環(huán)節(jié),以增加每個(gè)參與者需要等待其它的參與者確認(rèn)后方可進(jìn)行具體的操作。
「阻塞」這個(gè)動(dòng)作延后到這個(gè)「準(zhǔn)備提交」環(huán)節(jié)再做,使得阻塞范圍縮小為2PC的2/3(圖中背景×××和綠色部分)。正如上面的例子,在交換戒指之前增加了把戒指交給牧師的動(dòng)作。
同時(shí)還解決了協(xié)調(diào)者的單點(diǎn)問題。故障恢復(fù)或者新接替的協(xié)調(diào)者,可以利用「準(zhǔn)備提交」產(chǎn)生的狀態(tài)結(jié)果,來作為參與者和協(xié)調(diào)者在「提交」出現(xiàn)故障恢復(fù)后的界定依據(jù)。還是前面的例子,夸張點(diǎn),交換戒指的時(shí)候我失憶了,意識(shí)恢復(fù)后我只要看到牧師手掌上托著戒指或者我的手上已經(jīng)被戴好了戒指,就知道我的妻子已經(jīng)答應(yīng)了,我只要繼續(xù)給她做帶戒指這個(gè)事就好了。
新引入了timeout機(jī)制,在發(fā)生超時(shí)執(zhí)行默認(rèn)約定,避免了永久阻塞,也因此對(duì)多個(gè)參與者下的100%數(shù)據(jù)一致性作出了妥協(xié)。比如,協(xié)調(diào)者在向參與者A發(fā)送「doCommit」時(shí)timeout了,會(huì)引發(fā)廣播「abort」,但是這個(gè)「abort」又未能投遞到參與者B,導(dǎo)致參與者B執(zhí)行了「ACK」后的timeout默認(rèn)約定「commit」。
03 TCC
在國內(nèi),由于阿里的光環(huán)加持下TCC好像更火,風(fēng)頭蓋過了2PC和3PC。其本質(zhì)上是另辟蹊徑達(dá)到了和3PC類似的效果。
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有
通過運(yùn)用本地事務(wù)代替了全局事務(wù),使得可以不需要協(xié)調(diào)者的存在,避免了協(xié)調(diào)者的單點(diǎn)問題。
3PC中協(xié)調(diào)者的另一個(gè)作用:故障恢復(fù)后的數(shù)據(jù)一致性。在TTC里通過事務(wù)日志來確保。
這個(gè)概念最初是由Pat Helland于2007年提出的[7],那時(shí)還叫「Tentative-Confirmation-Cancellation」,在2008年的軟件開發(fā)2.0技術(shù)大會(huì)上支付寶CTO(程立)將其在國內(nèi)推廣開來。
以上這三種就是主流的DTS(Distributed Transaction Service)框架。值得一提的是,不管是3PC還是TCC,只要涉及到故障恢復(fù)或者重試機(jī)制,那么「冪等性」問題必須要提上來了。比如3PC中「提交」階段某個(gè)參與者和協(xié)調(diào)者同時(shí)掛了,但是這個(gè)參與者在掛之前已經(jīng)做了commit操作。那么故障恢復(fù)后其實(shí)沒人知道它是否執(zhí)行過了commit,協(xié)調(diào)者只會(huì)為了能100%確保commit指令被送達(dá),又會(huì)發(fā)起一次commit通知,這時(shí)候如果沒有做好「冪等性」就會(huì)發(fā)生重復(fù)commit的問題。
下面聊聊以「BASE」理論為基礎(chǔ)的解決方案。
01 異步消息——本地消息表
▲點(diǎn)擊圖片可查看大圖
這種實(shí)現(xiàn)方式的思路,源于ebay,與提出BASE理論在同一篇論文中[4]。設(shè)計(jì)思想是將遠(yuǎn)程分布式事務(wù)拆分成一系列的本地事務(wù),借助關(guān)系型數(shù)據(jù)庫中的表即可實(shí)現(xiàn)。
02 異步消息——不支持事務(wù)的MQ
▲點(diǎn)擊圖片可查看大圖
其實(shí)大部分的MQ都是不支持事務(wù)的,所以我們需要自己想辦法解決可能出現(xiàn)的MQ消息未能成功投遞出去的問題。有個(gè)便宜可以撿的是,如果需投遞的MQ消息條數(shù)僅有1的話,可以將本地事務(wù)的commit放于消息投遞之后即可避免此問題。偽代碼如下:
try{ beginTrans(); modifyLocalData1(); modifyLocalData2(); deliverMessageToMQ(); commitTrans(); }catch(Exception ex){ rollbackTrans(); }
03 異步消息——支持事務(wù)的MQ
▲點(diǎn)擊圖片可查看大圖
據(jù)我所知,目前唯一支持事務(wù)的MQ框架是RockerMQ,并且于近期才開源了事務(wù)部分實(shí)現(xiàn),《RocketMQ 4.3正式發(fā)布,支持分布式事務(wù)》(http://www.infoq.com/cn/news/2018/08/rocketmq-4.3-release)。這樣的確能省很多事~,直接放一張阿里方面給出的圖感受一下實(shí)現(xiàn)細(xì)節(jié)。
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有(點(diǎn)擊圖片可查看大圖)
不過其實(shí)有一個(gè)疑點(diǎn)我沒有去驗(yàn)證,有知道的小伙伴們可以留言下,就是RocketMQ是否有防止consumer(上圖中的訂閱方)在消費(fèi)完成后發(fā)送的ACK丟失的機(jī)制。如果能達(dá)到這點(diǎn),對(duì)于consumer內(nèi)部的方法冪等性需求就低了很多。
04 Saga
▲點(diǎn)擊圖片可查看大圖
Saga是1987年就提出的概念[8],核心是:
將一個(gè)分布式事務(wù)拆分為多個(gè)本地事務(wù),并且擊鼓傳花給下一個(gè),不用阻塞本地事務(wù)等待響應(yīng)。且允許嵌套至多一層子事務(wù)。
除了最后一個(gè)參與者之外,都需要定義一個(gè)「回滾」接口,便于在遇到無法進(jìn)行下去的情況下撤銷之前上游系統(tǒng)的修改。當(dāng)然這里的撤銷除了Update還可以是沖抵類的操作。
Saga原則上是個(gè)鏈?zhǔn)降摹搁L活事務(wù)」,整個(gè)處理耗時(shí)可能會(huì)很長。所以可以通過增加save point(保存點(diǎn),類似于游戲里的存檔),便于故障恢復(fù)和提速,如向前恢復(fù)(重試)和向后恢復(fù)(回滾)。不過,也可以并行多個(gè)子事務(wù),但一般在運(yùn)用中心節(jié)點(diǎn)的Saga模式中,如圖。
▲點(diǎn)擊圖片可查看大圖
只是在我們打破了鏈?zhǔn)揭?guī)則后必須要額外確保執(zhí)行了「回滾」之后再接收到「正向請(qǐng)求」,等于“請(qǐng)求無效”的效果。中心節(jié)點(diǎn)模式還有一個(gè)比較大的好處是能夠更好的避免事務(wù)之間的循環(huán)依賴關(guān)系。
05 Gossip協(xié)議
額外提一下,這個(gè)其實(shí)是一個(gè)具體的、運(yùn)用BASE理論實(shí)現(xiàn)的協(xié)議,借由Cassandra的熱火而讓更多人知道了。這協(xié)議一般會(huì)用于數(shù)據(jù)復(fù)制、P2P拓?fù)錁?gòu)造、故障探測等。
看這些案例我們可以發(fā)現(xiàn),基于「CAP」的解決方案都是在線的,而「Base」是允許離線的。好比前者是,累倒了必須得馬上爬起來繼續(xù)干貨,要不然就是失敗。而后者是,慢慢來,只要最終能干完。
不管怎樣,如果每個(gè)解決方案中增加「重試」和「回滾」會(huì)大大提升程序的自我修正能力,以降低需要人為介入的比例。識(shí)別是否需要人為介入的方式就是類似于「對(duì)賬」的機(jī)制,這個(gè)機(jī)制就是兜底的。最后還需要做一道選擇題來防止混亂:確保參與者的接口符合「冪等性」,或者在中間件里做到「正好一次(Exactly-once)」。
這些基于「BASE」的解決方案都是可以作為「CAP」解決方案出現(xiàn)問題時(shí)的PlanB來用的,起到補(bǔ)充作用。當(dāng)然,如非必要,可以優(yōu)先考慮基于「BASE」的方案,畢竟這才是天然易伸縮的,自然也能帶來更好的性能。
五、結(jié)語
解決方案如此多,所以不管我們是架構(gòu)師、還是在成為架構(gòu)師的路上,甚至在日常生活中,都需要養(yǎng)成Balance的習(xí)慣,找到那個(gè)最適合的方案。
最后還有一招終極大法 —— 減少冗余。
是亦彼也,彼亦是也,彼亦一是非,此亦一是非。 ——莊子
「事物都具有兩面性」,所以,在選擇走向分布式之前,慎重考慮下是否有必要,以免給自己徒增麻煩。
論文可后臺(tái)直接回復(fù)關(guān)鍵字“一致性”,打包下載。下篇將開啟「高可用」主題,敬請(qǐng)期待~
? 后臺(tái)回復(fù)“一致性”關(guān)鍵字,可打包下載喲~ [1] Distributed TP: The XA Specification , X/Open Company Ltd. , 1991 鏈接:https://publications.opengroup.org/c193 [2] Harvest, Yield, and Scalable Tolerant Systems, Armando Fox , Eric Brewer, 1999 鏈接:https://cs.uwaterloo.ca/~brecht/servers/readings-new2/harvest-yield.pdf [3] Brewer’s Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web, Seth Gilbert, Nancy Lynch, 2002 鏈接:https://pdfs.semanticscholar.org/24ce/ce61e2128780072bc58f90b8ba47f624bc27.pdf [4] Base: An Acid Alternative, Dan Pritchett, 2008 鏈接:http://delivery.acm.org/10.1145/1400000/1394128/p48-pritchett.pdf [5] Consensus Protocols: Two-Phase Commit, Henry Robinson, 2008 鏈接:http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/ [6] Consensus Protocols: Three-phase Commit, Henry Robinson, 2008 鏈接:http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/ [7] Life beyond Distributed Transactions:an Apostate’s Opinion, 2007 鏈接:https://cs.brown.edu/courses/cs227/archives/2012/papers/weaker/cidr07p15.pdf [8] Sagas, Hector Garcaa-Molrna & Kenneth Salem, 1987 鏈接:https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
作者:Zachary(個(gè)人×××號(hào):Zachary-ZF)
×××公眾號(hào)(首發(fā)):跨界架構(gòu)師。<-- 點(diǎn)擊查閱近期熱門文章
定期發(fā)表原創(chuàng)內(nèi)容:架構(gòu)設(shè)計(jì)丨分布式系統(tǒng)丨產(chǎn)品丨運(yùn)營丨一些深度思考。
掃碼加入小圈子 ↓
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。