京東二面:如何利用RocketMQ事務(wù)消息,來實(shí)現(xiàn)分布式事務(wù)?比如下單清空購物車的場景
前言
大家好,我是田螺。
分享一道京東的場景面試題:如何利用RocketMQ事務(wù)消息實(shí)現(xiàn)分布式事務(wù)?比如下單清空購物車場景。
我們?nèi)绾胃没卮疬@個(gè)問題呢?可以按照以下這幾個(gè)維度:
- 什么是分布式事務(wù)?
- 一條普通消息,從產(chǎn)生到消費(fèi)歷程
- 消息隊(duì)列的事務(wù)消息流程
- 事務(wù)消息的下單清空購物車場景
1. 什么是分布式事務(wù)
分布式事務(wù)是指在多個(gè)獨(dú)立的系統(tǒng)或數(shù)據(jù)庫之間執(zhí)行的事務(wù)操作,它確保所有參與者要么全部成功提交,要么全部回滾,以維持?jǐn)?shù)據(jù)一致性。
通常保證分布式事務(wù)的方案有:消息隊(duì)列的事務(wù)消息、TCC(Try-Confirm-Cancel)模式、Seata、二階段提交等。
2.一條消息從產(chǎn)生到消費(fè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ù)消息的過期時(shí)間和消費(fèi)進(jìn)度進(jìn)行管理。消費(fèi)者確認(rèn)消費(fèi)后,RocketMQ會(huì)記錄該消息的消費(fèi)狀態(tài),并在達(dá)到設(shè)定的過期時(shí)間后,從存儲(chǔ)中刪除該消息。這種機(jī)制確保了消息的可靠性和持久性。
3. 消息隊(duì)列的事務(wù)消息流程
在開始之前,我們先來了解一下,什么是半消息?
這個(gè)半消息,它不是說消息內(nèi)容不完整,它包含的內(nèi)容就是完整的消息內(nèi)容。它跟普通消息的唯一區(qū)別是,在事務(wù)提交之前,對(duì)于消費(fèi)者來說,這個(gè)消息是不可見的。
圖片
- 生產(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ù)器長時(shí)間沒有收到生產(chǎn)者的commit或者rollback,它會(huì)反查生產(chǎn)者,然后根據(jù)查詢到的結(jié)果執(zhí)行最終狀態(tài)。
4. 事務(wù)消息下的單清空購物車場景
我們看下,下訂單清空購物車的例子吧。訂單系統(tǒng)創(chuàng)建完訂單后,然后發(fā)消息給下游系統(tǒng)的購物車系統(tǒng),清空購物車。
- 生產(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)者(購物車系統(tǒng))。消費(fèi)者消費(fèi)完(即拿到訂單消息,清空購物車成功)就應(yīng)答ACK。
- 如果MQ服務(wù)器長時(shí)間沒有收到生產(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)重試嘛,接口支持冪等即可。
































