溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

RocketMQ事務(wù)消息學(xué)習(xí)及刨坑過程

發(fā)布時間:2020-07-17 09:33:53 來源:網(wǎng)絡(luò) 閱讀:793 作者:Java_老男孩 欄目:編程語言

一、背景

MQ組件是系統(tǒng)架構(gòu)里必不可少的一門利器,設(shè)計層面可以降低系統(tǒng)耦合度,高并發(fā)場景又可以起到削峰填谷的作用,從單體應(yīng)用到集群部署方案,再到現(xiàn)在的微服務(wù)架構(gòu),MQ憑借其優(yōu)秀的性能和高可靠性,得到了廣泛的認(rèn)可。
隨著數(shù)據(jù)量增多,系統(tǒng)壓力變大,開始出現(xiàn)這種現(xiàn)象:數(shù)據(jù)庫已經(jīng)更新了,但消息沒發(fā)出來,或者消息先發(fā)了,但后來數(shù)據(jù)庫更新失敗了,結(jié)果研發(fā)童鞋各種數(shù)據(jù)修復(fù),這種生產(chǎn)問題出現(xiàn)的概率不大,但讓人很郁悶。這個其實就是數(shù)據(jù)庫事務(wù)與MQ消息的一致性問題,簡單來講,數(shù)據(jù)庫的事務(wù)跟普通MQ消息發(fā)送無法直接綁定與數(shù)據(jù)庫事務(wù)綁定在一起,例如上面提及的兩種問題場景:

  1. 數(shù)據(jù)庫事務(wù)提交后發(fā)送MQ消息;
  2. MQ消息先發(fā),然后再提交數(shù)據(jù)庫事務(wù)。

場景1的問題是數(shù)據(jù)庫事務(wù)可能剛剛提交,服務(wù)器就宕機了,MQ消息沒發(fā)出去,場景2的問題就是MQ消息發(fā)送出去了,但數(shù)據(jù)庫事務(wù)提交失敗,又沒辦法追加已經(jīng)發(fā)出去的MQ消息,結(jié)果導(dǎo)致數(shù)據(jù)沒更新,下游已經(jīng)收到消息,最終事務(wù)出現(xiàn)不一致的情況。

二、事務(wù)消息的引出

我們以微服務(wù)架構(gòu)的購物場景為例,參照一下RocketMQ官方的例子,用戶A發(fā)起訂單,支付100塊錢操作完成后,能得到100積分,賬戶服務(wù)和會員服務(wù)是兩個獨立的微服務(wù)模塊,有各自的數(shù)據(jù)庫,按照上文提及的問題可能性,將會出現(xiàn)這些情況:

  • 如果先扣款,再發(fā)消息,可能錢剛扣完,宕機了,消息沒發(fā)出去,結(jié)果積分沒增加。
  • 如果先發(fā)消息,再扣款,可能積分增加了,但錢沒扣掉,白送了100積分給人家。
  • 錢正??哿?,消息也發(fā)送成功了,但會員服務(wù)實例消費消息出現(xiàn)問題,結(jié)果積分沒增加。

RocketMQ事務(wù)消息學(xué)習(xí)及刨坑過程

由此引出的是數(shù)據(jù)庫事務(wù)與MQ消息的事務(wù)一致性問題,rocketmq事務(wù)消息解決的問題:解決本地事務(wù)執(zhí)行與消息發(fā)送的原子性問題。這里界限一定要明白,是確保MQ生產(chǎn)端正確無誤地將消息發(fā)送出來,沒有多發(fā),也不會漏發(fā)。但至于發(fā)送后消費端有沒有正常的消費掉(如上面提及的第三種情況,錢正??哿耍⒁舶l(fā)了,但下游消費出問題導(dǎo)致積分不對),這種異常場景將由MQ消息消費失敗重試機制來保證,不在此次的討論范圍內(nèi)。

常用的MQ組件針對此場景都有自己的實現(xiàn)方案,如ActiveMQ使用AMQP協(xié)議(二階提交方式)保證消息正確發(fā)送,這里我們以RocketMQ為重點進(jìn)行學(xué)習(xí)。

三、RocketMQ事務(wù)消息設(shè)計思路

根據(jù)CAP理論,RocketMQ事務(wù)消息通過異步確保方式,保證事務(wù)的最終一致性。設(shè)計流程上借鑒兩階段提交理論,流程圖如下:

RocketMQ事務(wù)消息學(xué)習(xí)及刨坑過程

  1. 應(yīng)用模塊遇到要發(fā)送事務(wù)消息的場景時,先發(fā)送prepare消息給MQ。
  2. prepare消息發(fā)送成功后,應(yīng)用模塊執(zhí)行數(shù)據(jù)庫事務(wù)(本地事務(wù))。
  3. 根據(jù)數(shù)據(jù)庫事務(wù)執(zhí)行的結(jié)果,再返回Commit或Rollback給MQ。
  4. 如果是Commit,MQ把消息下發(fā)給Consumer端,如果是Rollback,直接刪掉prepare消息。
  5. 第3步的執(zhí)行結(jié)果如果沒響應(yīng),或是超時的,啟動定時任務(wù)回查事務(wù)狀態(tài)(最多重試15次,超過了默認(rèn)丟棄此消息),處理結(jié)果同第4步。
  6. MQ消費的成功機制由MQ自己保證。

四、RocketMQ事務(wù)消息實現(xiàn)流程

以RocketMQ 4.5.2版本為例,事務(wù)消息有專門的一個隊列RMQ_SYS_TRANS_HALF_TOPIC,所有的prepare消息都先往這里放,當(dāng)消息收到Commit請求后,就把消息再塞到真實的Topic隊列里,供Consumer消費,同時向RMQ_SYS_TRANS_OP_HALF_TOPIC塞一條消息。簡易流程圖如下:

RocketMQ事務(wù)消息學(xué)習(xí)及刨坑過程

上述流程中,請允許我這樣劃分模塊職責(zé):

  1. RocketMQ Client即我們工程中導(dǎo)入的依賴jar包,RocketMQ Broker端即部署的服務(wù)端,NameServer暫未體現(xiàn)。
  2. 應(yīng)用模塊成對出現(xiàn),上游為事務(wù)消息生產(chǎn)端,下游為事務(wù)消息消費端(事務(wù)消息對消費端是透明的,與普通消息一致)。

應(yīng)用模塊的事務(wù)因為中斷,或是其他的網(wǎng)絡(luò)原因,導(dǎo)致無法立即響應(yīng)的,RocketMQ當(dāng)做UNKNOW處理,RocketMQ事務(wù)消息還提供了一個補救方案:定時查詢事務(wù)消息的數(shù)據(jù)庫事務(wù)狀態(tài)

簡易流程圖如下:

RocketMQ事務(wù)消息學(xué)習(xí)及刨坑過程

五、結(jié)束語

本篇簡單介紹了事務(wù)消息的解決的場景和職責(zé)的界限,基本的設(shè)計思路和流程,在此借鑒學(xué)習(xí)了RocketMQ作者的圖稿,然后挑了部分代碼作簡要的講解,還是自己的刨坑過程,文章內(nèi)有任何不正確或不詳盡之處請留言指導(dǎo),謝謝。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI