京東二面:如何利用RocketMQ事務(wù)消息,來(lái)實(shí)現(xiàn)分布式事務(wù)?比如下單清空購(gòu)物車的場(chǎng)景
前言
大家好,我是田螺。
分享一道京東的場(chǎng)景面試題:如何利用RocketMQ事務(wù)消息實(shí)現(xiàn)分布式事務(wù)?比如下單清空購(gòu)物車場(chǎng)景。
我們?nèi)绾胃没卮疬@個(gè)問(wèn)題呢?可以按照以下這幾個(gè)維度:
- 什么是分布式事務(wù)?
 - 一條普通消息,從產(chǎn)生到消費(fèi)歷程
 - 消息隊(duì)列的事務(wù)消息流程
 - 事務(wù)消息的下單清空購(gòu)物車場(chǎng)景
 
1. 什么是分布式事務(wù)
分布式事務(wù)是指在多個(gè)獨(dú)立的系統(tǒng)或數(shù)據(jù)庫(kù)之間執(zhí)行的事務(wù)操作,它確保所有參與者要么全部成功提交,要么全部回滾,以維持?jǐn)?shù)據(jù)一致性。
通常保證分布式事務(wù)的方案有:消息隊(duì)列的事務(wù)消息、TCC(Try-Confirm-Cancel)模式、Seata、二階段提交等。
2.一條消息從產(chǎn)生到消費(fèi)歷程
我們先來(lái)看看:RocketMQ的一條普通的消息,從產(chǎn)生到被消費(fèi),經(jīng)歷的流程:
圖片
- 生產(chǎn)者產(chǎn)生消息,發(fā)送到MQ服務(wù)器(Broker)
 - MQ服務(wù)器收到消息后,將消息持久化到存儲(chǔ)系統(tǒng)。
 - MQ服務(wù)器返回ACk到生產(chǎn)者。
 - 消費(fèi)者從MQ服務(wù)器(Broker)拉取消息(Pull或Push,可以配置的)
 - 消費(fèi)者消費(fèi)完消息,響應(yīng)ACK
 - MQ服務(wù)器收到ACK,認(rèn)為消息消費(fèi)成功,即在存儲(chǔ)中刪除消息。
 
其實(shí),在RocketMQ中,消費(fèi)完消息后,消息不會(huì)立即被刪除,而是根據(jù)消息的過(guò)期時(shí)間和消費(fèi)進(jìn)度進(jìn)行管理。消費(fèi)者確認(rèn)消費(fèi)后,RocketMQ會(huì)記錄該消息的消費(fèi)狀態(tài),并在達(dá)到設(shè)定的過(guò)期時(shí)間后,從存儲(chǔ)中刪除該消息。這種機(jī)制確保了消息的可靠性和持久性。
3. 消息隊(duì)列的事務(wù)消息流程
在開(kāi)始之前,我們先來(lái)了解一下,什么是半消息?
這個(gè)半消息,它不是說(shuō)消息內(nèi)容不完整,它包含的內(nèi)容就是完整的消息內(nèi)容。它跟普通消息的唯一區(qū)別是,在事務(wù)提交之前,對(duì)于消費(fèi)者來(lái)說(shuō),這個(gè)消息是不可見(jiàn)的。
圖片
- 生產(chǎn)者產(chǎn)生消息,發(fā)送一條半消息到MQ服務(wù)器。
 - MQ收到消息后,將消息持久化到存儲(chǔ)系統(tǒng),這條消息的狀態(tài)是待發(fā)送狀態(tài)。
 - MQ服務(wù)器返回ACK確認(rèn)到生產(chǎn)者。
 - 生產(chǎn)者執(zhí)行本地事務(wù)
 - 如果本地事務(wù)執(zhí)行成功,即commit執(zhí)行結(jié)果到MQ服務(wù)器;如果執(zhí)行失敗,發(fā)送rollback。
 - 如果是正常的commit,MQ服務(wù)器更新消息狀態(tài)為可發(fā)送;如果是rollback,即刪除消息。
 - 如果消息狀態(tài)更新為可發(fā)送,則MQ服務(wù)器會(huì)push消息(可配置push還是pull)給消費(fèi)者。消費(fèi)者消費(fèi)完就回ACK。
 - 如果MQ服務(wù)器長(zhǎng)時(shí)間沒(méi)有收到生產(chǎn)者的commit或者rollback,它會(huì)反查生產(chǎn)者,然后根據(jù)查詢到的結(jié)果執(zhí)行最終狀態(tài)。
 
4. 事務(wù)消息下的單清空購(gòu)物車場(chǎng)景
我們看下,下訂單清空購(gòu)物車的例子吧。訂單系統(tǒng)創(chuàng)建完訂單后,然后發(fā)消息給下游系統(tǒng)的購(gòu)物車系統(tǒng),清空購(gòu)物車。
- 生產(chǎn)者(訂單系統(tǒng))產(chǎn)生消息,發(fā)送一條半消息到MQ服務(wù)器
 - MQ收到消息后,將消息持久化到存儲(chǔ)系統(tǒng),這條消息的狀態(tài)是待發(fā)送狀態(tài)。
 - MQ服務(wù)器返回ACK確認(rèn)到生產(chǎn)者,此時(shí)MQ不會(huì)觸發(fā)消息推送事件
 - 生產(chǎn)者執(zhí)行本地事務(wù)(訂單創(chuàng)建成功,提交事務(wù)消息)
 - 如果本地事務(wù)執(zhí)行成功,即commit執(zhí)行結(jié)果到MQ服務(wù)器;如果執(zhí)行失敗,發(fā)送rollback。
 - 如果是commit正常提交,MQ服務(wù)器更新消息狀態(tài)為可發(fā)送;如果是rollback,即刪除消息。
 - 如果消息狀態(tài)更新為可發(fā)送,則MQ服務(wù)器會(huì)push消息給消費(fèi)者(購(gòu)物車系統(tǒng))。消費(fèi)者消費(fèi)完(即拿到訂單消息,清空購(gòu)物車成功)就應(yīng)答ACK。
 - 如果MQ服務(wù)器長(zhǎng)時(shí)間沒(méi)有收到生產(chǎn)者的commit或者rollback,它會(huì)反查生產(chǎn)者,然后根據(jù)查詢到的結(jié)果(回滾操作或者重新發(fā)送消息)執(zhí)行最終狀態(tài)。
 
有些伙伴可能有疑惑,如果消費(fèi)者消費(fèi)失敗怎么辦呢?那數(shù)據(jù)是不是不一致啦?所以就需要消費(fèi)者消費(fèi)成功,執(zhí)行業(yè)務(wù)邏輯成功,再反饋ack嘛。如果消費(fèi)者消費(fèi)失敗,那就自動(dòng)重試嘛,接口支持冪等即可。















 
 
 













 
 
 
 