您好,登錄后才能下訂單哦!
這篇文章主要講解了“數(shù)據(jù)庫的分布式事務(wù)流程是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“數(shù)據(jù)庫的分布式事務(wù)流程是什么”吧!
眾所周知,數(shù)據(jù)庫能實(shí)現(xiàn)本地事務(wù),也就是說在同一個數(shù)據(jù)庫中,可以保證事務(wù)的原子性,就是全部成功或者失敗,上篇文章也寫過簡單的多數(shù)據(jù)源事務(wù)的解決方案(類似2PC)
但現(xiàn)在的系統(tǒng)往往采用微服務(wù)架構(gòu),業(yè)務(wù)系統(tǒng)擁有獨(dú)立的數(shù)據(jù)庫,因此就出現(xiàn)了跨多個數(shù)據(jù)庫的事務(wù)需求,這種事務(wù)即為“分布式事務(wù)”。
針對這樣的問題一般常用的方案有:
2PC/3PC (兩階段提交協(xié)議/三階段提交協(xié)議)
TCC (補(bǔ)償型)
基于可靠消息服務(wù)的分布式事務(wù)(異步確保型)
基于可靠消息服務(wù)的分布式事務(wù),我自己實(shí)現(xiàn)了一個基于rabbitmq的分布式事務(wù)中間件,shine-mq
一開始本來是想用來封裝mq的操作方便使用,后續(xù)迭代增加了分布式事務(wù)的功能。下面就來介紹下這個中間件:
在服務(wù)A處理任務(wù)A前,首先向Coordinator發(fā)送一條prepare(攜帶回查id)記錄,表示要開始這個分布式任務(wù)
Coordinator持久化prepare記錄后響應(yīng)服務(wù)A
服務(wù)A收到確認(rèn)應(yīng)答后,服務(wù)A處理任務(wù)A,成功后發(fā)送一條ready記錄,Coordinator將刪除之前對應(yīng)的prepare記錄,并持久化ready記錄和完整的消息
服務(wù)A在收到ready記錄和消息持久化的應(yīng)答后,就可以提交消息到消息中間件了,針對rabbitmq可以設(shè)置setPublisherConfirms(true)
以及實(shí)現(xiàn)setConfirmCallback
的回調(diào)來實(shí)現(xiàn)消息中間件持久化應(yīng)答服務(wù)A。這之后對于服務(wù)A來說就可以刪除之前的ready記錄和去處理其他任務(wù)了。
消息中間件(rabbitmq可以通過鏡像隊(duì)列來實(shí)現(xiàn)高可用)在確定將消息落盤之后就可以向服務(wù)B投遞消息
服務(wù)B消費(fèi)了該消息,并成功處理了任務(wù)B,服務(wù)B再向消息中間件返回一個確認(rèn)應(yīng)答,告訴消息中間件該消息已經(jīng)成功消費(fèi),此時,這個分布式事務(wù)完成。
上述是整個流程,服務(wù)A完成任務(wù)A后,到任務(wù)B執(zhí)行完成之間,會存在一定的時間差。在這個時間差內(nèi),整個系統(tǒng)處于數(shù)據(jù)不一致的狀態(tài),但這短暫的不一致性是可以接受的,因?yàn)榻?jīng)過短暫的時間后,系統(tǒng)又可以保持?jǐn)?shù)據(jù)一致性,滿足BASE理論。
BASE理論:
BA:Basic Available 基本可用
S:Soft State:柔性狀態(tài) 同一數(shù)據(jù)的不同副本的狀態(tài),可以不需要實(shí)時一致。
E:Eventual Consisstency:最終一致性 同一數(shù)據(jù)的不同副本的狀態(tài),可以不需要實(shí)時一致,但一定要保證經(jīng)過一定時間后仍然是一致的。
上面的是一個比較理想的流程,但是真正的環(huán)境會有很多突發(fā)情況,比如任務(wù)A處理失敗,那么需要進(jìn)入回滾流程
因?yàn)槿蝿?wù)A的異常對于服務(wù)A是可以直接捕獲的,回滾異常后刪除prepare記錄,服務(wù)A刪除之后便可以認(rèn)為回滾已經(jīng)完成,便可以去做其他的事情。
而該消息沒有投遞到消息中間件,則服務(wù)B沒有影響。此時系統(tǒng)又處于一致性狀態(tài),因?yàn)槿蝿?wù)A和任務(wù)B都沒有執(zhí)行。
Coordinator提供了接口可以自己來實(shí)現(xiàn),我默認(rèn)實(shí)現(xiàn)的方式是用redis。若要使用其他方式可以自行實(shí)現(xiàn)接口。
上圖表現(xiàn)的是發(fā)送ready記錄的時候,失敗了。這時候?qū)τ诜?wù)A是會收到異?;蛘呤詹坏綉?yīng)答,這時候可以直接將之前的任務(wù)A進(jìn)行回滾,任務(wù)A在回滾的時候會觸發(fā)刪除ready的操作。同樣如果異常是發(fā)生在發(fā)送prepare的情況下,這時候服務(wù)A還沒執(zhí)行任務(wù)也不會有影響。
分析完服務(wù)A,Coordinator和消息中間件之間的一些情況后,現(xiàn)在分析下消息中間件和服務(wù)B之間的一些特殊情況。
當(dāng)消息成功發(fā)布到消息中間件之后,服務(wù)A就可以做自己的事情去了,消息中間件會保證消息能成功投遞到服務(wù)B。這個就是消息中間件在消息投遞情況下的可靠性保證,具體流程是消息中間件向下游系統(tǒng)投遞完消息后便進(jìn)入阻塞等待狀態(tài),下游系統(tǒng)便立即進(jìn)行任務(wù)的處理,任務(wù)處理完成后便向消息中間件返回應(yīng)答。消息中間件收到確認(rèn)應(yīng)答后便認(rèn)為該事務(wù)處理完畢!如果消息在投遞過程中丟失,或消息的確認(rèn)應(yīng)答在返回途中丟失,那么消息中間件在等待確認(rèn)應(yīng)答超時之后就會重新投遞,直到下游消費(fèi)者返回消費(fèi)成功響應(yīng)為止。
這之間可以設(shè)置消息重試的次數(shù)和時間間隔,如果一直失敗這時候就會用到死信隊(duì)列。具體看下圖:
當(dāng)消息一直無法被正常消費(fèi),超過設(shè)置的重試閾值就會投遞到死信隊(duì)列,死信隊(duì)列的exchange和routeKey默認(rèn)是@DistributedTrans
中設(shè)置的值。
通過消費(fèi)死信隊(duì)列的消息來處理這種異常情況(可以設(shè)置短信或郵箱提醒,人工介入),這里暫時不實(shí)現(xiàn)服務(wù)A的回滾,因?yàn)樽尫?wù)A事先提供回滾接口,這無疑增加了額外的開發(fā)成本,業(yè)務(wù)系統(tǒng)的復(fù)雜度也將提高。對于一個業(yè)務(wù)系統(tǒng)的設(shè)計(jì)目標(biāo)是,在保證性能的前提下,最大限度地降低系統(tǒng)復(fù)雜度,從而能夠降低系統(tǒng)的運(yùn)維成本。
最后整理一下整個中間件的設(shè)計(jì)思路
上面已經(jīng)分析了一些異常情況,對于下游服務(wù)和消息中間件的原子性,我們可以通過消息中間件投遞的可靠性來保證(就是ACK模式,失敗或未收到應(yīng)答進(jìn)行重試)。 那么我們要實(shí)現(xiàn)分布式事務(wù),剩下的就是要保證上游服務(wù)執(zhí)行的任務(wù)和向消息中間件投遞消息這2個操作的原子性。
這時候一般就會有兩種方案,同步和異步通信。通過之前的時序圖,很顯然上游系統(tǒng)和消息中間件之間采用的是異步通信,也就是說當(dāng)上游服務(wù)提交完消息后便可以去做別的事情,接下來提交、回滾就完全交給消息中間件來完成,并且完全信任消息中間件,認(rèn)為它一定能正確地完成事務(wù)的提交或回滾。這主要是為了提高系統(tǒng)并發(fā)度,另外業(yè)務(wù)系統(tǒng)直接和用戶打交道,用戶體驗(yàn)尤為重要,因此這種異步通信方式能夠極大程度地降低用戶等待時間。
Rabbitmq其實(shí)有提供事務(wù)機(jī)制,使用txSelect(), txCommit()以及txRollback()來實(shí)現(xiàn),通過測試抓包發(fā)現(xiàn),Tx.Commit后直接發(fā)送Tx.Commit-Ok,兩者之間的時間間隔會比較長,簡單的測試能到300ms,這是很耗時的。所以我沒有用這種方式,而是引入一個Coordinator(協(xié)調(diào)者)來實(shí)現(xiàn)。
另外還有一個比較關(guān)鍵的daemon(守護(hù)線程),是處理在Coordinator一些錯誤超時的記錄(類似Rocketmq的超時詢問機(jī)制)。所以服務(wù)A除了實(shí)現(xiàn)正常的業(yè)務(wù)流程外,還需提供一個事務(wù)詢問的接口,供Coordinator調(diào)用,來保障服務(wù)A在執(zhí)行任務(wù)出現(xiàn)宕機(jī)的情況。當(dāng)有prepare超時就會觸發(fā)訪問這個回查接口,該接口會返回三種結(jié)果:
提交 將該消息投遞
回滾 直接將條消息丟棄
處理中 繼續(xù)等待,重置時間。
而超時的ready的消息,就直接撈起發(fā)送到消息中間件,因?yàn)橹灰莚eady消息持久化到協(xié)調(diào)者,那就說明服務(wù)A的任務(wù)已經(jīng)完成。
這樣就能保證上游服務(wù)和消息中間件的原子性了(具體可以看分布式事務(wù):消息可靠發(fā)送),再通過消息中間件可靠的投遞結(jié)合下游服務(wù),就完成了分布式事務(wù)。
感謝各位的閱讀,以上就是“數(shù)據(jù)庫的分布式事務(wù)流程是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對數(shù)據(jù)庫的分布式事務(wù)流程是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。