分布式消息隊列RocketMQ——事務(wù)消息——解決分布式事務(wù)的最佳實踐

說到分布式事務(wù),就會談到那個經(jīng)典的”賬號轉(zhuǎn)賬”問題:2個賬號砍聊,分布處于2個不同的DB背稼,或者說2個不同的子系統(tǒng)里面,A要扣錢玻蝌,B要加錢蟹肘,如何保證原子性词疼?

一般的思路都是通過消息中間件來實現(xiàn)“最終一致性”:A系統(tǒng)扣錢,然后發(fā)條消息給中間件疆前,B系統(tǒng)接收此消息寒跳,進行加錢。

但這里面有個問題:A是先update DB竹椒,后發(fā)送消息呢? 還是先發(fā)送消息米辐,后update DB胸完?

假設(shè)先update DB成功,發(fā)送消息網(wǎng)絡(luò)失敗翘贮,重發(fā)又失敗赊窥,怎么辦?

假設(shè)先發(fā)送消息成功狸页,update DB失敗锨能。消息已經(jīng)發(fā)出去了,又不能撤回芍耘,怎么辦址遇?

所以,這里下個結(jié)論: 只要發(fā)送消息和update DB這2個操作不是原子的斋竞,無論誰先誰后倔约,都是有問題的。

那這個問題怎么解決呢坝初?浸剩?

方案1–業(yè)務(wù)方自己實現(xiàn)

假設(shè)消息中間件沒有提供“事務(wù)消息”功能,比如你用的是Kafka鳄袍。那如何解決這個問題呢绢要?

解決方案如下:

(1)Producer端準(zhǔn)備1張消息表,把update DB和insert message這2個操作拗小,放在一個DB事務(wù)里面重罪。

(2)準(zhǔn)備一個后臺程序,源源不斷的把消息表中的message傳送給消息中間件十籍。失敗了蛆封,不斷重試重傳。允許消息重復(fù)勾栗,但消息不會丟惨篱,順序也不會打亂。

(3)Consumer端準(zhǔn)備一個判重表围俘。處理過的消息砸讳,記在判重表里面琢融。實現(xiàn)業(yè)務(wù)的冪等。但這里又涉及一個原子性問題:如果保證消息消費 + insert message到判重表這2個操作的原子性簿寂?

消費成功漾抬,但insert判重表失敗,怎么辦常遂?關(guān)于這個纳令,在Kafka的源碼分析系列,第1篇克胳, exactly once問題的時候平绩,有過討論。

通過上面3步漠另,我們基本就解決了這里update db和發(fā)送網(wǎng)絡(luò)消息這2個操作的原子性問題捏雌。

但這個方案的一個缺點就是:需要設(shè)計DB消息表,同時還需要一個后臺任務(wù)笆搓,不斷掃描本地消息性湿。導(dǎo)致消息的處理和業(yè)務(wù)邏輯耦合額外增加業(yè)務(wù)方的負(fù)擔(dān)。

方案2 – RocketMQ 事務(wù)消息

為了能解決該問題满败,同時又不和業(yè)務(wù)耦合肤频,RocketMQ提出了“事務(wù)消息”的概念。

具體來說葫录,就是把消息的發(fā)送分成了2個階段:Prepare階段和確認(rèn)階段着裹。

具體來說,上面的2個步驟米同,被分解成3個步驟:

(1) 發(fā)送Prepared消息

(2) update DB

(3) 根據(jù)update DB結(jié)果成功或失敗骇扇,Confirm或者取消Prepared消息。

可能有人會問了面粮,前2步執(zhí)行成功了少孝,最后1步失敗了怎么辦?這里就涉及到了RocketMQ的關(guān)鍵點:RocketMQ會定期(默認(rèn)是1分鐘)掃描所有的Prepared消息熬苍,詢問發(fā)送方稍走,到底是要確認(rèn)這條消息發(fā)出去?還是取消此條消息柴底?

具體代碼實現(xiàn)如下:

也就是定義了一個checkListener婿脸,RocketMQ會回調(diào)此Listener,從而實現(xiàn)上面所說的方案柄驻。

總結(jié):對比方案2和方案1狐树,RocketMQ最大的改變,其實就是把“掃描消息表”這個事情鸿脓,不讓業(yè)務(wù)方做抑钟,而是消息中間件幫著做了涯曲。

至于消息表,其實還是沒有省掉在塔。因為消息中間件要詢問發(fā)送方幻件,事物是否執(zhí)行成功,還是需要一個“變相的本地消息表”蛔溃,記錄事物執(zhí)行狀態(tài)绰沥。

人工介入

可能有人又要說了,無論方案1城榛,還是方案2揪利,發(fā)送端把消息成功放入了隊列,但消費端消費失敗怎么辦狠持?

消費失敗了,重試瞻润,還一直失敗怎么辦喘垂?是不是要自動回滾整個流程?

答案是人工介入绍撞。從工程實踐角度講正勒,這種整個流程自動回滾的代價是非常巨大的,不但實現(xiàn)復(fù)雜傻铣,還會引入新的問題章贞。比如自動回滾失敗,又怎么處理非洲?

對應(yīng)這種極低概率的case鸭限,采取人工處理,會比實現(xiàn)一個高復(fù)雜的自動化回滾系統(tǒng)两踏,更加可靠败京,也更加簡單。

在此我向大家推薦一個架構(gòu)學(xué)習(xí)交流群梦染。交流學(xué)習(xí)群號:938837867 暗號:555 里面會分享一些資深架構(gòu)師錄制的視頻錄像:有Spring赡麦,MyBatis,Netty源碼分析帕识,高并發(fā)泛粹、高性能、分布式肮疗、微服務(wù)架構(gòu)的原理晶姊,JVM性能優(yōu)化、分布式架構(gòu)等這些成為架構(gòu)師必備

?著作權(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é)果婚禮上胰坟,老公的妹妹穿的比我還像新娘因篇。我一直安慰自己,他們只是感情好笔横,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布竞滓。 她就那樣靜靜地躺著,像睡著了一般狠裹。 火紅的嫁衣襯著肌膚如雪虽界。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天涛菠,我揣著相機與錄音莉御,去河邊找鬼。 笑死俗冻,一個胖子當(dāng)著我的面吹牛礁叔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迄薄,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼琅关,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涣易,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤画机,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后新症,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體步氏,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年徒爹,在試婚紗的時候發(fā)現(xiàn)自己被綠了荚醒。 大學(xué)時的朋友給我發(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
  • 正文 我出身青樓,卻偏偏與公主長得像卡乾,于是被迫代替她去往敵國和親翼悴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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