摘要:?近日,Apache RocketMQ 社區(qū)正式發(fā)布4.3版本。此次發(fā)布不僅包括提升性能,減少內(nèi)存使用等原有特性增強(qiáng),還修復(fù)了部分社區(qū)提出的若干問題,更重要的是該版本開源了社區(qū)最為關(guān)心的分布式事務(wù)消息,而且實(shí)現(xiàn)了對外部組件的零依賴。
近日,Apache RocketMQ 社區(qū)正式發(fā)布4.3版本。此次發(fā)布不僅包括提升性能,減少內(nèi)存使用等原有特性增強(qiáng),還修復(fù)了部分社區(qū)提出的若干問題,更重要的是該版本開源了社區(qū)最為關(guān)心的分布式事務(wù)消息,而且實(shí)現(xiàn)了對外部組件的零依賴。接下來,本文將詳細(xì)探秘RocketMQ事務(wù)消息的設(shè)計(jì)原理以及實(shí)現(xiàn)機(jī)制。
一、需求緣起
在微服務(wù)架構(gòu)中,隨著服務(wù)的逐步拆分,數(shù)據(jù)庫私有已經(jīng)成為共識,這也導(dǎo)致所面臨的分布式事務(wù)問題成為微服務(wù)落地過程中一個非常難以逾越的障礙,但是目前尚沒有一個完整通用的解決方案。
其實(shí)不僅僅是在微服務(wù)架構(gòu)中,隨著用戶訪問量的逐漸上漲,數(shù)據(jù)庫甚至是服務(wù)的分片、分區(qū)、水平拆分、垂直拆分已經(jīng)逐漸成為較為常用的提升瓶頸的解決方案,因此越來越多的原子操作變成了跨庫甚至是跨服務(wù)的事務(wù)操作。最終結(jié)果是在對高性能、高擴(kuò)展性,高可用性的追求的道路上,我們開始逐漸放松對一致性的追求,但是在很多場景下,尤其是賬務(wù),電商等業(yè)務(wù)中,不可避免的存在著一致性問題,使得我們不得不去探尋一種機(jī)制,用以在分布式環(huán)境中保證事務(wù)的一致性。
二、理論基石
微服務(wù)使得單體架構(gòu)擴(kuò)展為分布式架構(gòu),在擴(kuò)展的過程中,逐漸喪失了單體架構(gòu)中數(shù)據(jù)源單一,可以直接依賴于數(shù)據(jù)庫進(jìn)行事務(wù)操作的能力,而關(guān)系型數(shù)據(jù)庫中,提供了強(qiáng)大的事務(wù)處理能力,可以滿足ACID(Atomicity,Consistency,Isolation,Durability)的特性,這種特性保證了數(shù)據(jù)操作的強(qiáng)一致性,這也是分布式環(huán)境中弱一致性以及最終一致性能夠得以實(shí)現(xiàn)的基礎(chǔ)。
數(shù)據(jù)一致性分為三個種類型:強(qiáng)一致性,弱一致性以及最終一致性,正如上文所述,數(shù)據(jù)庫實(shí)現(xiàn)的就是強(qiáng)一致性,能夠保證在寫入一份新的數(shù)據(jù)庫,立即使其可見。最終一致性是弱一致性的強(qiáng)化版,系統(tǒng)保證在沒有后續(xù)更新的前提下,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下,不一致窗口的時(shí)間主要受通信延遲,系統(tǒng)負(fù)載和復(fù)制副本的個數(shù)影響。
然而,微服務(wù)作為分布式系統(tǒng),同樣受CAP[1] 原理的制約,在CAP理論中,
C:Consistency
A:Availability
P:Partition tolerance
三者不可同時(shí)滿足,而服務(wù)化中,更多的是提升A以及P,在這個過程中不可避免的會降低對C的要求,因此,BASE理論隨之而來。
BASE[2] 理論來源于ebay在2008年ACM中發(fā)表的論文,BASE理論的基本原則有三個:Basically Available,Soft state,Eventually consistent,主要目的是為了提升分布式系統(tǒng)的可伸縮性,論文同樣闡述了如何對業(yè)務(wù)進(jìn)行調(diào)整以及折中的手段,BASE理論的提出為分布式事務(wù)的發(fā)展指出了一個方向。
在最終一致性的實(shí)現(xiàn)過程中,最基本的操作就是保證事務(wù)參與者的冪等性,所謂的冪等性,就是業(yè)務(wù)方能夠使用相關(guān)的手段,保證單個事務(wù)多次提交依然能夠保證達(dá)到同樣的目的。
三、當(dāng)前解決方案
1、2PC/3PC
談到分布式事務(wù),首先要說的就是2PC(two phase commit)方案,如下圖所示[3]:
2PC把事務(wù)的執(zhí)行分為兩個階段,第一個階段即prepare階段,這個階段實(shí)際上就是投票階段,協(xié)調(diào)者向參與者確認(rèn)是否可以共同提交,再得到全部參與者的所有回答后,協(xié)調(diào)者向所有的參與者發(fā)布共同提交或者共同回滾的指令,用以保證事務(wù)達(dá)到一致性。
但是分布式系統(tǒng)中的所有通信均存在著三種狀態(tài):成功,失敗,超時(shí)。其中,超時(shí)狀態(tài)的存在是我們在設(shè)計(jì)分布式系統(tǒng)時(shí)所面對的永遠(yuǎn)的痛,2PC同樣存在問題,尤其是在發(fā)送完可以提交的指令后,參與者在沒有收到提交或者回滾的指令時(shí),面對已經(jīng)上鎖的資源,面對已經(jīng)寫出去的undo或者redo日志,參與者會一時(shí)陷入手足無措的狀態(tài),為了解決這個問題,3PC應(yīng)運(yùn)而生,如下圖所示[4]:
3PC在commit之前增加了preCommit的過程,使得在參與者在收不到確認(rèn)時(shí),依然可以從容commit或者rollback,避免資源鎖定太久導(dǎo)致浪費(fèi)。但是3PC同樣存在著很多問題。實(shí)現(xiàn)起來非常復(fù)雜,因?yàn)楹茈y通過多次詢問來解決系統(tǒng)間分歧問題,尤其是存在超時(shí)狀態(tài)互不信任的分布式網(wǎng)絡(luò)中,這也就是著名的拜占庭將軍問題[5]。
總結(jié)一下,2PC是幾乎所有分布式事務(wù)算法的基礎(chǔ),后續(xù)的分布式事務(wù)算法幾乎都由此改進(jìn)而來,其優(yōu)缺點(diǎn)非常明顯:
? 優(yōu)點(diǎn):在于已經(jīng)有較為成熟的實(shí)現(xiàn)方案,比如XA。?
? 缺點(diǎn):XA是一個阻塞協(xié)議。服務(wù)在投票后需要等待協(xié)調(diào)器的決定,此時(shí)服務(wù)會阻塞并鎖定資源。由于其阻塞機(jī)制和最差時(shí)間復(fù)雜度高, 因此,這種設(shè)計(jì)不能適應(yīng)隨著事務(wù)涉及的服務(wù)數(shù)量增加而擴(kuò)展的需要,很難用于并發(fā)較高以及子事務(wù)聲明周期較長(long-running transactions)的分布式服務(wù)中。
2、SAGA
SAGA算法[6] 于1987年提出,是一種異步的分布式事務(wù)解決方案,其理論基礎(chǔ)在于,其假設(shè)所有事件按照順序推進(jìn),總能達(dá)到系統(tǒng)的最終一致性,因此saga需要服務(wù)分別定義提交接口以及補(bǔ)償接口,當(dāng)某個事務(wù)分支失敗時(shí),調(diào)用其它的分支的補(bǔ)償接口來進(jìn)行回滾,saga的具體實(shí)現(xiàn)分為兩種:Choreography以及Orchestration:
(1) Choreography:如下圖所示:
這種模式下不存在協(xié)調(diào)器的概念,每個節(jié)點(diǎn)均對自己的上下游負(fù)責(zé),在監(jiān)聽處理上游節(jié)點(diǎn)事件的同時(shí),對下游節(jié)點(diǎn)發(fā)布事件。
(2)Orchestration:存在中心節(jié)點(diǎn)的模式,如下圖所示:
該中心節(jié)點(diǎn),即協(xié)調(diào)器知道整個事務(wù)的分布狀態(tài),相比于無中心節(jié)點(diǎn)方式,該方式有著許多優(yōu)點(diǎn):
能夠避免事務(wù)之間的循環(huán)依賴關(guān)系;
參與者只需要執(zhí)行命令/回復(fù)(其實(shí)回復(fù)消息也是一種事件消息),降低參與者的復(fù)雜性;
開發(fā)測試門檻低;
在添加新步驟時(shí),事務(wù)復(fù)雜性保持線性,回滾更容易管理。因此大多數(shù)saga模型實(shí)現(xiàn)均采用了這種思路。
總結(jié)一下:SAGA模型的優(yōu)點(diǎn)在于其降低了事務(wù)粒度,使得事務(wù)擴(kuò)展更加容易,同時(shí)采用了異步化方式提升性能。但是其缺點(diǎn)在于很多時(shí)候很難定義補(bǔ)償接口,回滾代價(jià)高,而且由于SAGA在執(zhí)行過程中采用了先提交后補(bǔ)償?shù)乃悸愤M(jìn)行操作,所以單個子事務(wù)在并發(fā)提交時(shí)的隔離性很難保證。
3、TCC
TCC(Try-Confirm-Concel)模型[7] 同樣是一種補(bǔ)償性事務(wù),主要分為Try:檢查、保留資源,Confirm:執(zhí)行事務(wù),Concel:釋放資源三個階段,如下圖所示:
其中,活動管理器記錄了全局事務(wù)的推進(jìn)狀態(tài)以及各子事務(wù)的執(zhí)行狀態(tài),負(fù)責(zé)推進(jìn)各個子事務(wù)共同進(jìn)行提交或者回滾。同時(shí)負(fù)責(zé)在子事務(wù)處理超時(shí)后不停重試,重試不成功后轉(zhuǎn)手工處理,用以保證事務(wù)的最終一致性。
總結(jié)一下,相比于SAGA模型,其優(yōu)點(diǎn)在于嘗試階段僅僅只是對業(yè)務(wù)系統(tǒng)做檢測,并保留業(yè)務(wù)資源,并沒有真正提交,所以后續(xù)SAGA需要針對提交的事務(wù)做補(bǔ)償,而TCC則僅僅需要釋放保留資源,降低了補(bǔ)償成本;并且,由于在Try階段對資源進(jìn)行了保留鎖定,所以相比于SAGA模式,TCC模式擁有更高的隔離性。
缺點(diǎn):相比于SAGA模式,TCC模式多增加了一個狀態(tài),導(dǎo)致在業(yè)務(wù)開發(fā)過程中,復(fù)雜度上升,而且協(xié)調(diào)器與子事務(wù)的通信過程增加,狀態(tài)輪轉(zhuǎn)處理也更為復(fù)雜。
四、事物消息**
以購物場景為例,張三購買物品,賬戶扣款100元的同時(shí),需要保證在下游的會員服務(wù)中給該賬戶增加100積分。由于數(shù)據(jù)庫私有,所以導(dǎo)致在實(shí)際的操作過程中會出現(xiàn)很多問題,比如先發(fā)送消息,可能會因?yàn)榭劭钍?dǎo)致賬戶積分無故增加,如果先執(zhí)行扣款,則有可能因服務(wù)宕機(jī),導(dǎo)致積分不能增加,無論是先發(fā)消息還是先執(zhí)行本地事務(wù),都有可能導(dǎo)致出現(xiàn)數(shù)據(jù)不一致的結(jié)果。
事務(wù)消息的本質(zhì)就是為了解決此類問題,解決本地事務(wù)執(zhí)行與消息發(fā)送的原子性問題。目前,事務(wù)消息在多種分布式消息中間件種均有實(shí)現(xiàn),但是其實(shí)現(xiàn)方式思路卻各有不同。
1、傳統(tǒng)事務(wù)消息實(shí)現(xiàn)
傳統(tǒng)事務(wù)消息實(shí)現(xiàn),一種思路是依賴于AMQP協(xié)議用來確保消息發(fā)送成功,AMQP模式下需要在發(fā)送在發(fā)送事務(wù)消息時(shí)進(jìn)行兩階段提交,首先進(jìn)行tx_select開啟事務(wù),然后再進(jìn)行消息發(fā)送,最后進(jìn)行消息的commit或者是rollback。這個過程可以保證在消息發(fā)送成功的同時(shí)本地事務(wù)也一定成功執(zhí)行,但事務(wù)粒度不好控制,而且會導(dǎo)致性能急劇下降,同時(shí)依然無法解決本地事務(wù)執(zhí)行與消息發(fā)送的原子性問題。
還有另外一種思路,就是通過保證多條消息的同時(shí)可見性來保證事務(wù)一致性。但是此類消息事務(wù)實(shí)現(xiàn)機(jī)制更多的是用到consume-transform-produce場景中,其本質(zhì)還是用來保證消息自身事務(wù),并沒有把外部事務(wù)包含進(jìn)來。
2、RocketMQ事務(wù)消息
RocketMQ事務(wù)消息設(shè)計(jì)則主要是為了解決Producer端的消息發(fā)送與本地事務(wù)執(zhí)行的原子性問題,RocketMQ的設(shè)計(jì)中broker與producer端的雙向通信能力,使得broker天生可以作為一個事務(wù)協(xié)調(diào)者存在;而RocketMQ本身提供的存儲機(jī)制,則為事務(wù)消息提供了持久化能力;RocketMQ的高可用機(jī)制以及可靠消息設(shè)計(jì),則為事務(wù)消息在系統(tǒng)在發(fā)生異常時(shí),依然能夠保證事務(wù)的最終一致性達(dá)成。
2.1 RocketMQ 事務(wù)消息設(shè)計(jì)
事務(wù)消息作為一種異步確保型事務(wù), 將兩個事務(wù)分支通過MQ進(jìn)行異步解耦,RocketMQ事務(wù)消息的設(shè)計(jì)流程同樣借鑒了兩階段提交理論,整體交互流程如下圖所示:
事務(wù)發(fā)起方首先發(fā)送prepare消息到MQ。
在發(fā)送prepare消息成功后執(zhí)行本地事務(wù)。
根據(jù)本地事務(wù)執(zhí)行結(jié)果返回commit或者是rollback。
如果消息是rollback,MQ將刪除該prepare消息不進(jìn)行下發(fā),如果是commit消息,MQ將會把這個消息發(fā)送給consumer端。
如果執(zhí)行本地事務(wù)過程中,執(zhí)行端掛掉,或者超時(shí),MQ將會不停的詢問其同組的其它producer來獲取狀態(tài)。
Consumer端的消費(fèi)成功機(jī)制有MQ保證。
2.2 RocketMQ事務(wù)消息實(shí)現(xiàn)
RocketMQ事務(wù)消息在實(shí)現(xiàn)上充分利用了RocketMQ本身機(jī)制,在實(shí)現(xiàn)零依賴的基礎(chǔ)上,同樣實(shí)現(xiàn)了高性能、可擴(kuò)展、全異步等一系列特性。
在具體實(shí)現(xiàn)上,RocketMQ通過使用Half Topic 以及Operation Topic 兩個內(nèi)部隊(duì)列來存儲事務(wù)消息推進(jìn)狀態(tài),如下圖所示:
其中,Half Topic對應(yīng)隊(duì)列中存放著prepare消息,Operation Topic對應(yīng)的隊(duì)列則存放了prepare message對應(yīng)的commit/rollback消息,消息體中則是prepare message對應(yīng)的offset,服務(wù)端通過比對兩個隊(duì)列的差值來找到尚未提交的超時(shí)事務(wù),進(jìn)行回查。
在具體實(shí)現(xiàn)上,事務(wù)消息作為普通消息的一個應(yīng)用場景,在實(shí)現(xiàn)過程中進(jìn)行了分層抽象,從而避免了對RocketMQ原有存儲機(jī)制的修改,如下圖所示:
從用戶側(cè)來說,用戶需要分別實(shí)現(xiàn)本地事務(wù)執(zhí)行以及本地事務(wù)回查方法,因此只需關(guān)注本地事務(wù)的執(zhí)行狀態(tài)即可;而在service層,則對事務(wù)消息的兩階段提交進(jìn)行了抽象,同時(shí)針對超時(shí)事務(wù)實(shí)現(xiàn)了回查邏輯,通過不斷掃描當(dāng)前事務(wù)推進(jìn)狀態(tài),來不斷反向請求Producer端獲取超時(shí)事務(wù)的執(zhí)行狀態(tài),在避免事務(wù)掛起的同時(shí),也避免了Producer端的單點(diǎn)故障。而在存儲層,RocketMQ通過Bridge封裝了與底層隊(duì)列存儲的相關(guān)操作,用以操作兩個對應(yīng)的內(nèi)部隊(duì)列,用戶也可以依賴其它他存儲介質(zhì)實(shí)現(xiàn)自己的service,RocketMQ會通過ServiceProvider加載進(jìn)來。
從上述事務(wù)消息設(shè)計(jì)中可以看到,RocketMQ事務(wù)消息較好的解決了事務(wù)的最終一致性問題,事務(wù)發(fā)起方僅需要關(guān)注本地事務(wù)執(zhí)行以及實(shí)現(xiàn)回查接口給出事務(wù)狀態(tài)判定等實(shí)現(xiàn),而且在上游事務(wù)峰值高時(shí),可以通過消息隊(duì)列,避免對下游服務(wù)產(chǎn)生過大壓力。
事務(wù)消息不僅適用于上游事務(wù)對下游事務(wù)無依賴的場景,還可以與一些傳統(tǒng)分布式事務(wù)架構(gòu)相結(jié)合,而MQ的服務(wù)端作為天生的具有高可用能力的協(xié)調(diào)者,使得我們未來可以基于RocketMQ提供一站式輕量級分布式事務(wù)解決方案,用以滿足各種場景下的分布式事務(wù)需求。
作者介紹:
馮嘉,Apache RocketMQ聯(lián)合創(chuàng)始人,Linux OpenMessaging標(biāo)準(zhǔn)創(chuàng)始人。阿里巴巴高級技術(shù)專家,帶領(lǐng)團(tuán)隊(duì)、社區(qū)打造了中國分布式云計(jì)算領(lǐng)域第一個Apache頂級開源中間件項(xiàng)目,創(chuàng)立分布式消息領(lǐng)域的國際標(biāo)準(zhǔn)OpenMessaging。
馮嘉作為阿里巴巴 RocketMQ技術(shù)負(fù)責(zé)人,具有豐富的分布式軟件架構(gòu)、高并發(fā)網(wǎng)站設(shè)計(jì)、性能調(diào)優(yōu)經(jīng)驗(yàn),擁有國內(nèi)外多項(xiàng)分布式、推薦領(lǐng)域的專利授權(quán)。目前專注于大規(guī)模分布式系統(tǒng)、分布式消息引擎、流計(jì)算領(lǐng)域,關(guān)注 Hbase/Hadoop/Spark/Flink等大數(shù)據(jù)技術(shù)棧。
杜恒,阿里巴巴技術(shù)專家,Apache RocketMQ內(nèi)核控,擁有多年分布式系統(tǒng)研發(fā)經(jīng)驗(yàn),對Microservice, Messaging,Storage等領(lǐng)域有深刻理解,擁有多年金融領(lǐng)域開發(fā)設(shè)計(jì)經(jīng)驗(yàn)。目前專注RocketMQ內(nèi)核優(yōu)化以及Messaging生態(tài)建設(shè)。
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
評論
查看更多