您好,登錄后才能下訂單哦!
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ù)可能剛剛提交,服務(wù)器就宕機了,MQ消息沒發(fā)出去,場景2的問題就是MQ消息發(fā)送出去了,但數(shù)據(jù)庫事務(wù)提交失敗,又沒辦法追加已經(jīng)發(fā)出去的MQ消息,結(jié)果導(dǎo)致數(shù)據(jù)沒更新,下游已經(jīng)收到消息,最終事務(wù)出現(xiàn)不一致的情況。
我們以微服務(wù)架構(gòu)的購物場景為例,參照一下RocketMQ官方的例子,用戶A發(fā)起訂單,支付100塊錢操作完成后,能得到100積分,賬戶服務(wù)和會員服務(wù)是兩個獨立的微服務(wù)模塊,有各自的數(shù)據(jù)庫,按照上文提及的問題可能性,將會出現(xiàn)這些情況:
由此引出的是數(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í)。
根據(jù)CAP理論,RocketMQ事務(wù)消息通過異步確保方式,保證事務(wù)的最終一致性。設(shè)計流程上借鑒兩階段提交理論,流程圖如下:
以RocketMQ 4.5.2版本為例,事務(wù)消息有專門的一個隊列RMQ_SYS_TRANS_HALF_TOPIC,所有的prepare消息都先往這里放,當(dāng)消息收到Commit請求后,就把消息再塞到真實的Topic隊列里,供Consumer消費,同時向RMQ_SYS_TRANS_OP_HALF_TOPIC塞一條消息。簡易流程圖如下:
上述流程中,請允許我這樣劃分模塊職責(zé):
應(yīng)用模塊的事務(wù)因為中斷,或是其他的網(wǎng)絡(luò)原因,導(dǎo)致無法立即響應(yīng)的,RocketMQ當(dāng)做UNKNOW處理,RocketMQ事務(wù)消息還提供了一個補救方案:定時查詢事務(wù)消息的數(shù)據(jù)庫事務(wù)狀態(tài)
簡易流程圖如下:
本篇簡單介紹了事務(wù)消息的解決的場景和職責(zé)的界限,基本的設(shè)計思路和流程,在此借鑒學(xué)習(xí)了RocketMQ作者的圖稿,然后挑了部分代碼作簡要的講解,還是自己的刨坑過程,文章內(nèi)有任何不正確或不詳盡之處請留言指導(dǎo),謝謝。
免責(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)容。