利用rabbitmq的延遲隊(duì)列實(shí)現(xiàn)延遲(定時(shí))任務(wù)

通常在應(yīng)用開發(fā)中我們會(huì)碰到定時(shí)任務(wù)的需求,比如未付款訂單,超過一定時(shí)間后,系統(tǒng)自動(dòng)取消訂單并釋放占有物品。

許多同學(xué)的第一反應(yīng)就是通過spring的schedule定時(shí)任務(wù)輪詢數(shù)據(jù)庫來實(shí)現(xiàn),這種方案有一下幾點(diǎn)劣勢(shì):

(1)消耗系統(tǒng)內(nèi)存,由于定時(shí)任務(wù)一直在系統(tǒng)中占著進(jìn)程,比較消耗內(nèi)存

(2)增加了數(shù)據(jù)庫的壓力,這個(gè)提現(xiàn)在兩方面,一是長(zhǎng)時(shí)間占著數(shù)據(jù)庫的連接,而是查詢基數(shù)大

(3)存在較大的時(shí)間誤差

如果我們利用第三方插件如rabbitmq來實(shí)現(xiàn),就可以解決以上幾種問題。

那么如何實(shí)現(xiàn)呢?

rabbitmq的消息TTL和死信Exchange結(jié)合

1.消息的TTL(Time To Live)

消息的TTL就是消息的存活時(shí)間。RabbitMQ可以對(duì)隊(duì)列和消息分別設(shè)置TTL。對(duì)隊(duì)列設(shè)置就是隊(duì)列沒有消費(fèi)者連著的保留時(shí)間,也可以對(duì)每一個(gè)單獨(dú)的消息做單獨(dú)的設(shè)置。超過了這個(gè)時(shí)間,我們認(rèn)為這個(gè)消息就死了,稱之為死信。如果隊(duì)列設(shè)置了,消息也設(shè)置了,那么會(huì)取小的。所以一個(gè)消息如果被路由到不同的隊(duì)列中,這個(gè)消息死亡的時(shí)間有可能不一樣(不同的隊(duì)列設(shè)置)。這里單講單個(gè)消息的TTL,因?yàn)樗攀菍?shí)現(xiàn)延遲任務(wù)的關(guān)鍵。可以通過設(shè)置消息的expiration字段或者x-message-ttl屬性來設(shè)置時(shí)間,兩者是一樣的效果。

2.Dead Letter Exchanges

Exchage的概念在這里就不在贅述。一個(gè)消息在滿足如下條件下,會(huì)進(jìn)死信路由,記住這里是路由而不是隊(duì)列,一個(gè)路由可以對(duì)應(yīng)很多隊(duì)列。

①.一個(gè)消息被Consumer拒收了,并且reject方法的參數(shù)里requeue是false。也就是說不會(huì)被再次放在隊(duì)列里,被其他消費(fèi)者使用。

②. 上面的消息的TTL到了,消息過期了。

③. 隊(duì)列的長(zhǎng)度限制滿了。排在前面的消息會(huì)被丟棄或者扔到死信路由上。

Dead Letter Exchange其實(shí)就是一種普通的exchange,和創(chuàng)建其他exchange沒有兩樣。只是在某一個(gè)設(shè)置Dead Letter Exchange的隊(duì)列中有消息過期了,會(huì)自動(dòng)觸發(fā)消息的轉(zhuǎn)發(fā),發(fā)送到Dead Letter Exchange中去。

3.實(shí)現(xiàn)延遲隊(duì)列

盜圖一張

延遲隊(duì)列的工作流程

4.在springboot中的應(yīng)用

a.配置消息隊(duì)列

在消息隊(duì)列的參數(shù)配置中,先建立消息隊(duì)列和死信交換機(jī),并將其綁定起來,代碼片段如下


TTL隊(duì)列和死信交換機(jī)的配置

b.配置轉(zhuǎn)發(fā)隊(duì)列(TTL隊(duì)列中的消息過期后,轉(zhuǎn)發(fā)目標(biāo)隊(duì)列,即Queue2)


轉(zhuǎn)發(fā)隊(duì)列(死信接收隊(duì)列)

c.監(jiān)聽轉(zhuǎn)發(fā)隊(duì)列,并進(jìn)行業(yè)務(wù)處理

轉(zhuǎn)發(fā)隊(duì)列的監(jiān)聽處理

測(cè)試,利用junit測(cè)試,發(fā)送具有過期時(shí)間的消息


過期消息發(fā)送測(cè)試

配置完畢。

注意:由于隊(duì)列的先進(jìn)先出特性,只有當(dāng)過期的消息到了隊(duì)列的頂端(隊(duì)首),才會(huì)被真正的丟棄或者進(jìn)入死信隊(duì)列。所以在考慮使用RabbitMQ來實(shí)現(xiàn)延遲任務(wù)隊(duì)列的時(shí)候,需要確保業(yè)務(wù)上每個(gè)任務(wù)的延遲時(shí)間是一致的。如果遇到不同的任務(wù)類型需要不同的延時(shí)的話,需要為每一種不同延遲時(shí)間的消息建立單獨(dú)的消息隊(duì)列。

參考:https://www.cnblogs.com/haoxinyue/p/6613706.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容