天天看點

RabbitMQ如何實作延遲隊列?

延遲隊列存儲的對象肯定是對應的延遲消息,所謂”延遲消息”是指當消息被發送以後,并不想讓消費者立即拿到消息,而是等待指定時間後,消費者才拿到這個消息進行消費。

場景一:在訂單系統中,一個使用者下單之後通常有30分鐘的時間進行支付,如果30分鐘之内沒有支付成功,那麼這個訂單将進行一場處理。這是就可以使用延遲隊列将訂單資訊發送到延遲隊列。

場景二:使用者希望通過手機遠端遙控家裡的智能裝置在指定的時間進行工作。這時候就可以将使用者指令發送到延遲隊列,當指令設定的時間到了再将指令推送到隻能裝置。

AMQP協定,以及RabbitMQ本身沒有直接支援延遲隊列的功能,但是可以通過TTL和DLX模拟出延遲隊列的功能。

TTL(Time To Live)

RabbitMQ可以針對Queue和Message設定 x-message-tt,來控制消息的生存時間,如果逾時,則消息變為dead letter

RabbitMQ針對隊列中的消息過期時間有兩種方法可以設定。

A: 通過隊列屬性設定,隊列中所有消息都有相同的過期時間。

B: 對消息進行單獨設定,每條消息TTL可以不同。

如果同時使用,則消息的過期時間以兩者之間TTL較小的那個數值為準。消息在隊列的生存時間一旦超過設定的TTL值,就成為dead letter

DLX (Dead-Letter-Exchange)

RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可選)兩個參數,如果隊列内出現了dead letter,則按照這兩個參數重新路由。

x-dead-letter-exchange:出現dead letter之後将dead letter重新發送到指定exchange

x-dead-letter-routing-key:指定routing-key發送

隊列出現dead letter的情況有:

消息或者隊列的TTL過期

隊列達到最大長度

消息被消費端拒絕(basic.reject or basic.nack)并且requeue=false

利用DLX,當消息在一個隊列中變成死信後,它能被重新publish到另一個Exchange。這時候消息就可以重新被消費。

首先建立2個exchange和2個queue:

exchange_delay_begin:這個是producer端發送時調用的exchange, 将消息發送至queue_dealy_begin中。

queue_delay_begin: 通過routingKey=”delay”綁定exchang_delay_begin, 同時配置DLX=exchange_delay_done, 當消息變成死信時,發往exchange_delay_done中。

exchange_delay_done: 死信的exchange, 如果不配置x-dead-letter-routing-key則采用原有預設的routingKey,即queue_delay_begin綁定exchang_delay_beghin采用的“delay”。

queue_delay_done:消息在TTL到期之後,最終通過exchang_delay_done發送值此queue,消費端通過消費此queue的消息,即可以達到延遲的效果。

1. 建立exchange和queue的代碼(當然這裡可以通過RabbitMQ的管理界面來實作,無需code相關代碼):

2. consumer端代碼:

3. producer端代碼:設定消息的延遲時間為1min。

在建立完exchange和queue之後,首先執行consumer端的代碼,之後執行producer端的代碼,待producer發送完畢之後,檢視consumer端的輸出:

可以看到延遲1min消費了相關消息。大功告成~

<a href="http://blog.csdn.net/u014308482/article/details/53036770">rabbitmq 實作延遲隊列的兩種方式</a>

<a href="http://blog.csdn.net/u013256816/article/details/54916011">RabbitMQ之TTL(Time-To-Live 過期時間)</a>

<a href="http://blog.csdn.net/u013256816/article/details/54933065">RabbitMQ之死信隊列</a>