Python知識分享網(wǎng) - 專業(yè)的Python學(xué)習(xí)網(wǎng)站 學(xué)Python,上Python222
RocketMQ實(shí)踐:確保消息不丟失與順序性的高效策略 PDF 下載
發(fā)布于:2024-01-05 09:59:32
(假如點(diǎn)擊沒反應(yīng),多刷新兩次就OK!)

RocketMQ實(shí)踐:確保消息不丟失與順序性的高效策略 PDF 下載  圖1

 

 

 

資料內(nèi)容:

 

2、RocketMQ消息零丟失方案
1》 生產(chǎn)者使用事務(wù)消息機(jī)制保證消息零丟失
這個(gè)結(jié)論比較容易理解,因?yàn)镽ocketMQ的事務(wù)消息機(jī)制就是為了保證零丟失來設(shè)計(jì)的,并且經(jīng)過阿里
的驗(yàn)證,肯定是非??孔V的。
但是如果深入一點(diǎn)的話,我們還是要理解下這個(gè)事務(wù)消息到底是不是靠譜。我們以最常見的電商訂單場
景為例,來簡單分析下事務(wù)消息機(jī)制如何保證消息不丟失。我們看下下面這個(gè)流程圖:

1、為什么要發(fā)送個(gè)half消息?有什么用?
這個(gè)half消息是在訂單系統(tǒng)進(jìn)行下單操作前發(fā)送,并且對下游服務(wù)的消費(fèi)者是不可見的。那這個(gè)消息的
作用更多的體現(xiàn)在確認(rèn)RocketMQ的服務(wù)是否正常。相當(dāng)于嗅探下RocketMQ服務(wù)是否正常,并且通知
RocketMQ,我馬上就要發(fā)一個(gè)很重要的消息了,你做好準(zhǔn)備。
2.half消息如果寫入失敗了怎么辦?
如果沒有half消息這個(gè)流程,那我們通常是會在訂單系統(tǒng)中先完成下單,再發(fā)送消息給MQ。這時(shí)候?qū)?br /> 入消息到MQ如果失敗就會非常尷尬了。而half消息如果寫入失敗,我們就可以認(rèn)為MQ的服務(wù)是有問題
的,這時(shí),就不能通知下游服務(wù)了。我們可以在下單時(shí)給訂單一個(gè)狀態(tài)標(biāo)記,然后等待MQ服務(wù)正常后
再進(jìn)行補(bǔ)償操作,等MQ服務(wù)正常后重新下單通知下游服務(wù)。
3.訂單系統(tǒng)寫數(shù)據(jù)庫失敗了怎么辦?
這個(gè)問題我們同樣比較下沒有使用事務(wù)消息機(jī)制時(shí)會怎么辦?如果沒有使用事務(wù)消息,我們只能判斷下
單失敗,拋出了異常,那就不往MQ發(fā)消息了,這樣至少保證不會對下游服務(wù)進(jìn)行錯(cuò)誤的通知。但是這
樣的話,如果過一段時(shí)間數(shù)據(jù)庫恢復(fù)過來了,這個(gè)消息就無法再次發(fā)送了。當(dāng)然,也可以設(shè)計(jì)另外的補(bǔ)
償機(jī)制,例如將訂單數(shù)據(jù)緩存起來,再啟動一個(gè)線程定時(shí)嘗試往數(shù)據(jù)庫寫。而如果使用事務(wù)消息機(jī)制,
就可以有一種更優(yōu)雅的方案。
如果下單時(shí),寫數(shù)據(jù)庫失敗(可能是數(shù)據(jù)庫崩了,需要等一段時(shí)間才能恢復(fù))。那我們可以另外找個(gè)地方
把訂單消息先緩存起來(Redis、文本或者其他方式),然后給RocketMQ返回一個(gè)UNKNOWN狀態(tài)。這樣
RocketMQ就會過一段時(shí)間來回查事務(wù)狀態(tài)。我們就可以在回查事務(wù)狀態(tài)時(shí)再嘗試把訂單數(shù)據(jù)寫入數(shù)據(jù)
庫,如果數(shù)據(jù)庫這時(shí)候已經(jīng)恢復(fù)了,那就能完整正常的下單,再繼續(xù)后面的業(yè)務(wù)。這樣這個(gè)訂單的消息
就不會因?yàn)閿?shù)據(jù)庫臨時(shí)崩了而丟失。
4.half消息寫入成功后RocketMQ掛了怎么辦?
我們需要注意下,在事務(wù)消息的處理機(jī)制中,未知狀態(tài)的事務(wù)狀態(tài)回查是由RocketMQ的Broker主動發(fā)
起的。也就是說如果出現(xiàn)了這種情況,那RocketMQ就不會回調(diào)到事務(wù)消息中回查事務(wù)狀態(tài)的服務(wù)。這
時(shí),我們就可以將訂單一直標(biāo)記為"新下單"的狀態(tài)。而等RocketMQ恢復(fù)后,只要存儲的消息沒有丟
失,RocketMQ就會再次繼續(xù)狀態(tài)回查的流程。
5.下單成功后如何優(yōu)雅的等待支付成功?
在訂單場景下,通常會要求下單完成后,客戶在一定時(shí)間內(nèi),例如10分鐘,內(nèi)完成訂單支付,支付完成
后才會通知下游服務(wù)進(jìn)行進(jìn)一步的營銷補(bǔ)償。
如果不用事務(wù)消息,那通常會怎么辦?
最簡單的方式是啟動一個(gè)定時(shí)任務(wù),每隔一段時(shí)間掃描訂單表,比對未支付的訂單的下單時(shí)間,將超過
時(shí)間的訂單回收。這種方式顯然是有很大問題的,需要定時(shí)掃描很龐大的一個(gè)訂單信息,這對系統(tǒng)是個(gè)
不小的壓力。
那更進(jìn)一步的方案是什么呢?是不是就可以使用RocketMQ提供的延遲消息機(jī)制。往MQ發(fā)一個(gè)延遲1分
鐘的消息,消費(fèi)到這個(gè)消息后去檢查訂單的支付狀態(tài),如果訂單已經(jīng)支付,就往下游發(fā)送下單的通知。
而如果沒有支付,就再發(fā)一個(gè)延遲1分鐘的消息。最終在第十個(gè)消息時(shí)把訂單回收。這個(gè)方案就不用對
全部的訂單表進(jìn)行掃描,而只需要每次處理一個(gè)單獨(dú)的訂單消息。
那如果使用上了事務(wù)消息呢?我們就可以用事務(wù)消息的狀態(tài)回查機(jī)制來替代定時(shí)的任務(wù)。在下單時(shí),給
Broker返回一個(gè)UNKNOWN的未知狀態(tài)。而在狀態(tài)回查的方法中去查詢訂單的支付狀態(tài)。這樣整個(gè)業(yè)
務(wù)邏輯就會簡單很多。我們只需要配置RocketMQ中的事務(wù)消息回查次數(shù)(默認(rèn)15次)和事務(wù)回查間隔時(shí)
間(messageDelayLevel),就可以更優(yōu)雅的完成這個(gè)支付狀態(tài)檢查的需求。
6、事務(wù)消息機(jī)制的作用
整體來說,在訂單這個(gè)場景下,消息不丟失的問題實(shí)際上就還是轉(zhuǎn)化成了下單這個(gè)業(yè)務(wù)與下游服務(wù)的業(yè)
務(wù)的分布式事務(wù)一致性問題。而事務(wù)一致性問題一直以來都是一個(gè)非常復(fù)雜的問題。而RocketMQ的事
務(wù)消息機(jī)制,實(shí)際上只保證了整個(gè)事務(wù)消息的一半,他保證的是訂單系統(tǒng)下單和發(fā)消息這兩個(gè)事件的事
務(wù)一致性,而對下游服務(wù)的事務(wù)并沒有保證。但是即便如此,也是分布式事務(wù)的一個(gè)很好的降級方案。
目前來看,也是業(yè)內(nèi)最好的降級方案