Apache RocketMQ-4.3.0正式Release了事務(wù)消息的特性,順著最近的這個(gè)熱點(diǎn)。第一篇文章,就來聊一下在軟件工程學(xué)上的長久的難題——分布式事務(wù)(Distributed Transaction)。
??祍sl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!這個(gè)技術(shù)也在各個(gè)諸如阿里,騰訊等大廠的內(nèi)部,被廣泛地實(shí)現(xiàn),利用及優(yōu)化。但是由于理論上就有難點(diǎn),所以分布式事務(wù)就隱晦得成了大廠對(duì)于小廠的技術(shù)壁壘。相信來看這篇文章的同學(xué),一定都聽過很多關(guān)于分布式事務(wù)的術(shù)語,比較二階段提交,TCC,最終一致性等,所以這里也不多普及概念。
我們直接上正題,利用RocketMQ設(shè)計(jì)自己的分布式事務(wù)組件。
舉個(gè)虛擬場景引出問題
用戶從農(nóng)行
轉(zhuǎn)賬100元去招行
?,農(nóng)行的系統(tǒng)和招行的系統(tǒng)分別部署在自己的機(jī)房,系統(tǒng)之間通過消息
進(jìn)行通信,防止過度耦合。
整個(gè)模型可以不恰當(dāng)?shù)妹枋鰹椋恨r(nóng)行扣了100元后,發(fā)送“已經(jīng)扣款”的消息給招行,招行收到消息,知道農(nóng)行扣款成功了,然后在招行賬戶上加100元。
問題是,農(nóng)行這邊,方案1. 先扣100元再發(fā)消息,方案2. 先發(fā)消息再扣100元
整理下整個(gè)事務(wù)不一致的場景:
方案1,
農(nóng)行扣100后成功,但是消息發(fā)送失敗,招行沒有加100
方案2,
消息發(fā)送成功,但是農(nóng)行扣100元失敗,招行收到消息加了100
各位同學(xué)應(yīng)該已經(jīng)發(fā)現(xiàn)問題所在了,扣款和發(fā)送消息這兩個(gè)事情,沒有辦法通過調(diào)換順序?qū)崿F(xiàn)「同時(shí)成功」,或者「同時(shí)失敗」。如果前者成功,后者失敗,就會(huì)造成不一致。
RocketMQ,以下簡稱RMQ,為了實(shí)現(xiàn)事務(wù)消息引入了一種新的消息類型:TransactionMsg
一個(gè)完整的事務(wù)消息分成兩個(gè)部分:
HalfMsg(Prepare)
?+?Commit/RollbackMsg
Producer發(fā)送了HalfMsg后,由于HalfMsg不是一個(gè)完整的事務(wù)消息,Consumer無法立刻就消費(fèi)到該消息,Producer可以對(duì)HalfMsg進(jìn)行Commit或者Rollback來終結(jié)事務(wù)(EndTransacaction)。只有當(dāng)Commit了HalfMsg后,Consumer才能消費(fèi)到這條消息。RMQ會(huì)定期去向Producer詢問,是否可以Commit或者Rollback那些由于錯(cuò)誤沒有被終結(jié)的HalfMsg來結(jié)束它們的生命周期,以達(dá)成事務(wù)最終的一致。
依然是剛剛的轉(zhuǎn)賬場景,我們用RMQ事務(wù)消息來優(yōu)化下流程:
農(nóng)行向RMQ同步發(fā)送HalfMsg,消息中攜帶農(nóng)行即將要扣100元的信息
農(nóng)行HalfMsg成功發(fā)送后,執(zhí)行數(shù)據(jù)庫本地事務(wù),在自己的系統(tǒng)中扣100元
農(nóng)行查看本地事務(wù)執(zhí)行情況
本地事務(wù)返回成功,農(nóng)行向RMQ提交(Commit)HalfMsg
招行系統(tǒng)訂閱了RMQ,順利收到農(nóng)行已經(jīng)扣款100元的信息
圖1:RMQ事務(wù)消息原理
同樣得,我們逐個(gè)來分析下這個(gè)流程是不是會(huì)出現(xiàn)不一致:
農(nóng)行發(fā)送HalfMsg是同步發(fā)送(Sync),如果HalfMsg發(fā)送不成功,壓根就不會(huì)執(zhí)行本地事務(wù)
發(fā)送HalfMsg成功,但是農(nóng)行扣款**本地事務(wù)失敗,也沒事,如果本地事務(wù)沒有成功,立刻就發(fā)送Rollback去回滾HalfMsg**。就當(dāng)之前啥事都沒有發(fā)生過
農(nóng)行本地事務(wù)成功了,但是Commit卻失敗了,但是由于HalfMsg已經(jīng)在RMQ中,RMQ就能通過定時(shí)程序讓農(nóng)行重新檢測本地事務(wù)是否成功,重新Commit。Rollback失敗了也是同理
剛剛討論的案例是非常理想化的,整個(gè)分布式事務(wù)中,只涉及到了金額的變化,但是,真正的線上系統(tǒng),作為消息發(fā)送方的本地事務(wù)可能就非常復(fù)雜,可能涉及到了幾十張不同的表,那RMQ用定時(shí)器來Check HalfMsg,難道去查下涉及該事務(wù)的每一張表的數(shù)據(jù)是否提交成功?顯然這種方案非常業(yè)務(wù)侵入非常大,并且很難組件化。所以需要在本地事務(wù)中設(shè)計(jì)一張Transaction表,將業(yè)務(wù)表和Transaction綁定在同一個(gè)本地事務(wù)中,如果農(nóng)行的扣款本地事務(wù)成功時(shí),Transaction中應(yīng)當(dāng)已經(jīng)記錄該TransactionId的狀態(tài)為「已完成」。當(dāng)最后需要檢查時(shí),只需要檢查對(duì)應(yīng)的TransactionId的狀態(tài)是否是「已完成」就好,而不用關(guān)心具體的業(yè)務(wù)數(shù)據(jù)。
再談一個(gè)小細(xì)節(jié),
細(xì)心的同學(xué)可能發(fā)現(xiàn),剛剛No.3的討論其實(shí)是有點(diǎn)不嚴(yán)謹(jǐn)?shù)?,RMQ在調(diào)用Commit或者Rollback時(shí),用的是Oneway
的方式,熟悉RMQ源碼的話,知道這種網(wǎng)絡(luò)調(diào)用是只單向發(fā)送Request,不會(huì)去獲取Response。消息發(fā)送性能上是有非常大的提升的,但是如果真的發(fā)送失敗,Producer是不會(huì)知曉的,最后只能通過定時(shí)檢查HalfMsg才能終結(jié)事務(wù)。
public void endTransactionOneway(
final String addr,
final EndTransactionRequestHeader requestHeader,
final String remark,
final long timeoutMillis
) throws RemotingException, MQBrokerException, InterruptedException {
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.END_TRANSACTION, requestHeader);
request.setRemark(remark);
// 使用Oneway發(fā)送end transaction類型的
this.remotingClient.invokeOneway(addr, request, timeoutMillis);
}
不是所有的MQ都能支持事務(wù)消息,如何使用一般的MQ來搭建分布式事務(wù)組件,甚至抽象成一個(gè)事務(wù)SOA服務(wù)?
其實(shí)仔細(xì)分析下RMQ的事務(wù)消息,我們可以把它拆解成兩個(gè)部分:
事務(wù)管理器
?+?消息
所謂的事務(wù)管理器,就是對(duì)于事務(wù)的預(yù)備(Prepare)、提交(Commit)和回滾(Rollback)的管理,另外還包含預(yù)備事務(wù)的定時(shí)檢查器。
消息,指的就是一般的同步消息,發(fā)送后能明確得到發(fā)送結(jié)果,用于事務(wù)系統(tǒng)與業(yè)務(wù)系統(tǒng)解耦。幾乎所有的分布式MQ都是支持這種消息的。
我們來設(shè)計(jì)下自己的DistributedTransaction SOA,以下簡稱DT-SOA
圖2:分布式事務(wù)服務(wù)化
流程還是沒有變,但分布式事務(wù)不再強(qiáng)依賴RMQ,而是用一般的MQ代替:
系統(tǒng)A發(fā)送事務(wù),首先調(diào)用DT-SOA的Prepare方法準(zhǔn)備開啟事務(wù),由于是同步調(diào)用,獲取SendResult,如果發(fā)送成功,拿到全局分布式事務(wù)的ID——TID
系統(tǒng)A用獲取到的TID執(zhí)行本地事務(wù),本地事務(wù)中包含Transaction狀態(tài)表,成功后將TID對(duì)應(yīng)的狀態(tài)置為“已完成”
系統(tǒng)A調(diào)用DT-SOA提交事務(wù),DT-SOA用MQ發(fā)送同步消息給系統(tǒng)B
更多精彩的文章,請(qǐng)關(guān)注我的微信公眾號(hào): 艾瑞克的技術(shù)江湖
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站欄目:構(gòu)建基于RocketMQ的分布式事務(wù)服務(wù)-創(chuàng)新互聯(lián)
URL分享:http://jinyejixie.com/article10/ccpido.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、網(wǎng)站制作、搜索引擎優(yōu)化、品牌網(wǎng)站制作、靜態(tài)網(wǎng)站、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容