從0開始寫框架(三)—分布式事務(wù)解決方案

本文作者:羅海鵬,叩丁狼高級講師颗管。原創(chuàng)文章,轉(zhuǎn)載請注明出處比吭。

回顧

??上一篇文章我們說到吧慢,各種分布式事務(wù)解決方案的特點瓢剿,其中最后提到了可靠消息事務(wù)最終一致性這種解決方案坠韩,而我們這篇文章的標題也是它氢惋,沒錯,我們接下來要詳細的分析該解決方案的實現(xiàn)細節(jié)了传趾,上一篇文章在介紹該解決方案時宽涌,已經(jīng)說了那個執(zhí)行流程分析圖,僅僅只是一個粗略圖而已决侈,實際上功茴,可靠消息事務(wù)最終一致性的設(shè)計是非常復雜的栖茉。那么為什么要花那么多時間來詳細分析它的實現(xiàn)細節(jié)呢?原因是接下來我們開發(fā)的這個分布式事務(wù)框架娜饵,就是使用可靠消息事務(wù)最終一致性的方案肺魁,選擇它的理由很簡單瘾晃,就是因為它比較復雜,所以實現(xiàn)的過程中涡真,能學到的技術(shù)和得到的鍛煉比較多东亦。

總體設(shè)計

先來看看以下這張設(shè)計圖:

總體設(shè)計流程圖

??這張設(shè)計圖是在上一章的執(zhí)行流程基礎(chǔ)上歹啼,再補充了一些細節(jié)岁钓,實際上腰根,要完成可靠消息最終一致性东帅,并不是僅僅依靠消息隊列就行了,還需要很多其他組件共同協(xié)作萄金,這些組件在以不修改業(yè)務(wù)方法的前提下,通過組件或者擴展的方式整合到項目中,具有可插拔性季俩,這樣的話,才能做到對業(yè)務(wù)項目的侵入性低的目的欺矫。
??那么通過上述的總體設(shè)計流程圖,我們可以提取出以下幾個組件:1、攔截器組件(Interceptor)迂烁,2、事務(wù)協(xié)調(diào)組件(Coordinator)狰域,3、事務(wù)日志存儲組件(Repository),4线梗、可靠消息組件(MQ),5、補償調(diào)用組件(Invoker)竹挡,6、定時器組件(Scheduler)轩娶,7椰弊、初始化組件(Initiator)。接下來并蝗,我們詳細的看看,每一個組件是什么陪每,做什么,并且它們之間如何協(xié)調(diào)工作的。
注意:以下所涉及的代碼不是真正的實現(xiàn),而是偽代碼

1草穆、攔截器組件(Interceptor)

??通過設(shè)計圖的分析灌灾,我們可以知道,有兩個地方需要攔截的悲柱,一個是在發(fā)起RPC請求時锋喜,需要對請求進行攔截,一個是RPC請求到達了遠程目的方法后豌鸡,執(zhí)行方法前的攔截。

  • 發(fā)起RPC請求的攔截
    ??在發(fā)起RPC請求的攔截器中共耍,我們需要告訴事務(wù)協(xié)調(diào)者,自己的角色是事務(wù)發(fā)起者的角色,這一步是至關(guān)重要的爽室,因為一個事務(wù)發(fā)起者需要保存這多個事務(wù)參與者的信息筐高,舉個例子:轉(zhuǎn)賬(transfer)業(yè)務(wù)方法開啟了分布式事務(wù)获雕,并且transfer方法中有兩個遠程方法,分別是扣錢(decrease)和加錢(augment)。那transfer就是事務(wù)發(fā)起者脚线,decrease和augment就是事務(wù)參與者梆惯。
    ??transfer在分別調(diào)用decrease和augment者兩個遠程方法時,先進入了攔截器咏瑟,把decrease和augment這兩個事務(wù)參與者的信息添加到transfer這個事務(wù)發(fā)起者中瓢姻,也就是我們常說的一對多關(guān)系朋贬。
    ??在執(zhí)行完了transfer方法后,整個transfer這個事務(wù)發(fā)起者下有多少個事務(wù)參與者都添加完畢了,接下來就把自己的這個事務(wù)發(fā)起者角色告訴事務(wù)協(xié)調(diào)者灰嫉,到這里茬末,發(fā)起RPC請求的攔截器做的事情就結(jié)束短蜕,接下來就是事務(wù)協(xié)調(diào)者做的事情了氢架,我們后面在來講事務(wù)協(xié)調(diào)者。 結(jié)合以下分析圖理解:
    發(fā)起請求攔截分析圖
  • 執(zhí)行業(yè)務(wù)方法前的攔截
    ??跟發(fā)起RPC請求的攔截類似朋魔,在RPC請求到達了目的方法后岖研,開始執(zhí)行方法,但在執(zhí)行方法前铺厨,我們還需要做一些事情缎玫,就是把自己作為事務(wù)參與者的角色告知事務(wù)協(xié)調(diào)者,還是以攔截器的形式做這些事情解滓,但是攔截器又如何知道自己將要執(zhí)行的業(yè)務(wù)方法就是事務(wù)參與者呢赃磨?這就要回到RPC請求上了:transfer遠程RPC調(diào)用decrease和augment時,需要給這兩個地址追加一個參數(shù)洼裤,該參數(shù)具體是什么東西沒有關(guān)系邻辉,只要能知道事務(wù)發(fā)起者是誰就行了(暫且我們叫該參數(shù)為transactionId),那么decrease和augment所在的過濾器獲取RPC參數(shù)名為transactionId的值腮鞍,發(fā)現(xiàn)有值值骇,那就把自己確定問事務(wù)參與者,并且通過transactionId的值知道移国,自己所屬的事務(wù)發(fā)起者是誰吱瘩。 結(jié)合以下分析圖理解:
    執(zhí)行方法攔截分析圖

2、事務(wù)協(xié)調(diào)組件(Coordinator)

??事務(wù)協(xié)調(diào)者是所有分布式事務(wù)解決方案都會有的一個核心處理器迹缀,它作為各個分布在不同JVM中的本地事務(wù)間接通訊的橋梁使碾。在可靠消息事務(wù)最終一致性的解決方案中,它主要負責事務(wù)的發(fā)起祝懂、事務(wù)的參與票摇、事務(wù)的提交、事務(wù)出錯處理砚蓬、發(fā)送事務(wù)MQ消息等矢门,凡是涉及到事務(wù)的生命周期操作,都經(jīng)過它做統(tǒng)籌處理灰蛙。它直接操作下一個要講解的組件—事務(wù)日志存儲組件(Repository)祟剔。

3、事務(wù)日志存儲組件(Repository)

??事務(wù)日志存儲組件主要負責儲存事務(wù)日志的操作摩梧,事務(wù)日志的核心信息為:事務(wù)id物延、事務(wù)類和方法,事務(wù)狀態(tài)障本、事務(wù)角色教届、事務(wù)參與者集合。所以針對事務(wù)的操作非常多驾霜,會涉及到多線程和大并發(fā)的問題案训,所以這里到時候需要考慮線程安全和支持大并發(fā)的設(shè)計。 結(jié)合以下分析圖理解:

事務(wù)協(xié)調(diào)和事務(wù)日志存儲分析圖

4粪糙、可靠消息組件(MQ)

??可靠消息組件顧名思義强霎,就是發(fā)送MQ消息的,而消息體就是:事務(wù)發(fā)起者中的各個事務(wù)參與者詳細信息蓉冈,還是以我們上面的例子說明:transfer在分別調(diào)用decrease和augment者兩個遠程方法城舞,transfer是事務(wù)發(fā)起者,decrease和augment是transfer的事務(wù)參與者寞酿,在transfer方法執(zhí)行完后家夺,得到一個事務(wù)信息,該信息傳給了事務(wù)協(xié)調(diào)者伐弹,事務(wù)協(xié)調(diào)者會遍歷該事務(wù)中的參與者列表拉馋,每遍歷到一個事務(wù)參與者,就往該參與者所監(jiān)聽的MQ消息地點發(fā)送消息惨好,消息體的核心信息為:“參與者的業(yè)務(wù)方法”煌茴。這樣的話參與者如果在執(zhí)行業(yè)務(wù)的過程中報錯了,還可以到MQ中獲取消息日川,重新執(zhí)行業(yè)務(wù)方法蔓腐。結(jié)合以下分析圖理解(為了分析圖更直觀,刪減了一些流程):

發(fā)送消息和監(jiān)聽消息

5龄句、補償調(diào)用組件(Invoker)

??消息補償組件起到的作用就是:各個事務(wù)參與者在各種異常情況下回论,沒法正常執(zhí)行業(yè)務(wù)方法,比如:事務(wù)發(fā)起者transfer調(diào)用了decrease和augment撒璧,但是augment所在的服務(wù)器宕機透葛,導致不能接受RPC請求,這樣事務(wù)就有問題了卿樱,decrease扣錢成功僚害,augment加錢失敗。這時MQ就起作用了繁调,我們剛剛已經(jīng)知道萨蚕,在transfer方法執(zhí)行完后,會給MQ的decrease和augment地點發(fā)送消息蹄胰,消息體有個核心信息:“執(zhí)行的業(yè)務(wù)方法”岳遥。那這樣,augment所在的服務(wù)器重啟后裕寨,馬上監(jiān)聽到MQ的augment地點消息浩蓉,然后把消息交給事務(wù)補償調(diào)用組件(Invoker)派继,Invoker重新調(diào)用消息體中的業(yè)務(wù)方法,完成事務(wù)補償捻艳。 同理驾窟,如果augment所在的服務(wù)器沒有宕機,但卻在執(zhí)行業(yè)務(wù)方法的過程中報錯认轨,則MQ會新增一條消息绅络,等著augment獲取,并重新執(zhí)行業(yè)務(wù)方法嘁字。那為什么報錯了會自動往MQ發(fā)消息呢恩急?這個涉及到定時器組件(Scheduler),我們下面再詳細分析定時器的作用纪蜒。
??但這里需要特別注意的是衷恭,Invoker需要做好冪等性的操作,因為transfer方法執(zhí)行完了纯续,事務(wù)協(xié)調(diào)者就會往decrease和augment兩個事務(wù)參與者監(jiān)聽的消息地點發(fā)送消息匾荆,所以,不管decrease和augment是否正常執(zhí)行杆烁,消息都會發(fā)送出去牙丽,那問題就來了,通過RPC已經(jīng)正常調(diào)用了一次兔魂,然后監(jiān)聽到MQ消息又調(diào)用了一次烤芦,就調(diào)用了兩次了,所以事務(wù)補償調(diào)用組件需要做好冪等性析校,防止業(yè)務(wù)方法執(zhí)行多次构罗。

6、定時器組件(Scheduler)

??定時器組件(Scheduler)就是我們剛剛提到的一種情況的問題:服務(wù)器正常運行智玻,能接收RPC遠程調(diào)用請求遂唧,但是執(zhí)行過程中報錯,那這時吊奢,定時器就起作用了盖彭,定時器在項目初始化時就需要設(shè)置好。
??業(yè)務(wù)方法執(zhí)行報錯页滚,進入捕捉異常流程召边,通知事務(wù)協(xié)調(diào)者,把對應(yīng)的事務(wù)日志狀態(tài)修改為“錯誤”狀態(tài)裹驰,然后定時器每隔一段時間掃描狀態(tài)為“錯誤”的事務(wù)日志隧熙,掃描到之后,即往MQ發(fā)送消息幻林,那接下來的流程贞盯,又回到了事務(wù)補償?shù)牧鞒塘艘裟睢J聞?wù)補償成功后,需要把對應(yīng)的事務(wù)日志狀態(tài)修改為“提交”狀態(tài)躏敢。結(jié)合以下分析圖理解(為了分析圖更直觀症昏,刪減了一些流程):

定時器執(zhí)行分析

7、初始化組件(Initiator)

??這一個組件就不用多說了父丰,我們設(shè)置定時器,監(jiān)聽MQ的Destination掘宪,還有做一些初始化參數(shù)設(shè)置等蛾扇,都是需要在這里執(zhí)行。

總結(jié)

??分布式事務(wù)本身就是一件非常復雜的事情魏滚,所以在設(shè)計階段就要考慮的比較完善镀首,這樣在具體實現(xiàn)的時候才不會有太多問題。而通過這篇文章的講解鼠次,已經(jīng)從宏觀上了解了這種“可靠消息事務(wù)最終一致性”解決方案的來龍去脈更哄,相當于設(shè)計稿就有了。那接下來腥寇,我們就要根據(jù)這個設(shè)計稿來做具體功能的實現(xiàn)成翩。在寫代碼實現(xiàn)的過程中,由于會接觸到更細節(jié)的問題赦役,這些細節(jié)又不可能在設(shè)計階段面面俱到麻敌,所以很可能會出現(xiàn)具體實現(xiàn)與設(shè)計不一樣的情況,這是正常的掂摔,只要在合理的調(diào)整范圍內(nèi)术羔,大體流程上并沒有改變就行了。

想獲取更多技術(shù)干貨乙漓,請前往叩丁狼官網(wǎng):http://www.wolfcode.cn/all_article.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末级历,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叭披,更是在濱河造成了極大的恐慌寥殖,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涩蜘,死亡現(xiàn)場離奇詭異扛禽,居然都是意外死亡,警方通過查閱死者的電腦和手機皱坛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門编曼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人剩辟,你說我怎么就攤上這事掐场⊥樱” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵熊户,是天一觀的道長萍膛。 經(jīng)常有香客問我,道長嚷堡,這世上最難降的妖魔是什么蝗罗? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮蝌戒,結(jié)果婚禮上串塑,老公的妹妹穿的比我還像新娘。我一直安慰自己北苟,他們只是感情好桩匪,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著友鼻,像睡著了一般傻昙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彩扔,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天妆档,我揣著相機與錄音,去河邊找鬼虫碉。 笑死过吻,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蔗衡。 我是一名探鬼主播纤虽,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绞惦!你這毒婦竟也來了逼纸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤济蝉,失蹤者是張志新(化名)和其女友劉穎杰刽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體王滤,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡贺嫂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雁乡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片第喳。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖踱稍,靈堂內(nèi)的尸體忽然破棺而出曲饱,到底是詐尸還是另有隱情悠抹,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布扩淀,位于F島的核電站楔敌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏驻谆。R本人自食惡果不足惜卵凑,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胜臊。 院中可真熱鬧勺卢,春花似錦、人聲如沸区端。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽织盼。三九已至,卻和暖如春酱塔,著一層夾襖步出監(jiān)牢的瞬間沥邻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工沉眶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镣煮,地道東北人启具。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像邮利,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子垃帅,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容