RabbitMQ是目前非常熱門的一款消息中間件,不管是互聯網大廠還是中小企業都在大量使用。作為一名合格的開發者,有必要了解一下相關知識,RabbitMQ(一):RabbitMQ快速入門已經入門RabbitMQ,本文介紹RabbitMQ的高級特性。
過期時間(TTL)
Time To Live,也就是生存時間,是一條消息在隊列中的最大存活時間,單位是毫秒。了解Redis的朋友應該一看就明白,二者很像。
RabbitMQ可以對消息和隊列設置TTL。
RabbitMQ支持設置消息的過期時間,在消息發送的時候可以進行指定,每條消息的過期時間可以不同。
RabbitMQ支持設置隊列的過期時間,從消息入隊列開始計算,直到超過了隊列的超時時間配置,那么消息會變成死信,自動清除。
如果兩種方式一起使用,則過期時間以兩者中較小的那個數值為准。
當然也可以不設置TTL,不設置表示消息不會過期;如果設置為0,則表示除非此時可以直接將消息投遞到消費者,否則該消息將被立即丟棄。
消息確認
為了保證消息從隊列可靠地到達消費者,RabbitMQ提供了消息確認機制。消費者訂閱隊列的時候,可以指定autoAck參數,當autoAck為true的時候,RabbitMQ采用自動確認模式,RabbitMQ自動把發送出去的消息設置為確認,然后從內存或者硬盤中刪除,而不管消費者是否真正消費到了這些消息。當autoAck為false的時候,RabbitMQ會等待消費者回復的確認信號,收到確認信號之后才從內存或者磁盤中刪除消息。
消息確認機制是RabbitMQ消息可靠性投遞的基礎,只要設置autoAck參數為false,消費者就有足夠的時間處理消息,不用擔心處理消息的過程中消費者進程掛掉后消息丟失的問題。
持久化
消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保證消息可靠性的呢?答案就是消息持久化。持久化可以防止在異常情況下丟失數據。RabbitMQ的持久化分為三個部分:交換器持久化、隊列持久化和消息的持久化。
交換器持久化可以通過在聲明隊列時將durable參數設置為true。如果交換器不設置持久化,那么在RabbitMQ服務重啟之后,相關的交換器元數據會丟失,不過消息不會丟失,只是不能將消息發送到這個交換器了。
隊列的持久化能保證其本身的元數據不會因異常情況而丟失,但是不能保證內部所存儲的消息不會丟失。要確保消息不會丟失,需要將其設置為持久化。隊列的持久化可以通過在聲明隊列時將durable參數設置為true。
設置了隊列和消息的持久化,當RabbitMQ服務重啟之后,消息依然存在。如果只設置隊列持久化或者消息持久化,重啟之后消息都會消失。
當然,也可以將所有的消息都設置為持久化,但是這樣做會影響RabbitMQ的性能,因為磁盤的寫入速度比內存的寫入要慢得多。對於可靠性不是那么高的消息可以不采用持久化處理以提高整體的吞吐量。魚和熊掌不可兼得,關鍵在於選擇和取舍。在實際中,需要根據實際情況在可靠性和吞吐量之間做一個權衡。
死信隊列
當消息在一個隊列中變成死信之后,他能被重新發送到另一個交換器中,這個交換器成為死信交換器,與該交換器綁定的隊列稱為死信隊列。。
消息變成死信有下面幾種情況:
- 消息被拒絕。通過調用basic.reject或者basic.nack並且設置requeue=false。
- 消息過期
- 隊列達到最大長度
DLX也是一個正常的交換器,和一般的交換器沒有區別,他能在任何的隊列上面被指定,實際上就是設置某個隊列的屬性。當這個隊列中有死信的時候,RabbitMQ會自動將這個消息重新發送到設置的交換器上,進而被路由到另一個隊列,我們可以監聽這個隊列中消息做相應的處理。
死信隊列設置:
-
設置死信隊列的exchange和queue,然后進行綁定
-
- Exchange:dlx.exchange
- Queue:dlx.queue
- RoutingKey:#
-
然后進行正常聲明交換器、隊列、綁定,只不過我們需要在隊列上加一個參數即可:arguments.put(“x-dead-letter-exchange”,“dlx.exchange”)
死信隊列有什么用?
當發生異常的時候,消息不能夠被消費者正常消費,被加入到了死信隊列中。后續的程序可以根據死信隊列中的內容分析當時發生的異常,進而改善和優化系統。
延遲隊列
一般的隊列,消息一旦進入隊列就會被消費者立即消費。延遲隊列就是進入該隊列的消息會被消費者延遲消費,延遲隊列中存儲的對象是的延遲消息,“延遲消息”是指當消息被發送以后,等待特定的時間后,消費者才能拿到這個消息進行消費。
延遲隊列用於需要延遲工作的場景。最常見的使用場景:淘寶或者天貓我們都使用過,用戶在下單之后通常有30分鍾的時間進行支付,如果這30分鍾之內沒有支付成功,那么訂單就會自動取消。除了延遲消費,延遲隊列的典型應用場景還有延遲重試。比如消費者從隊列里面消費消息失敗了,可以延遲一段時間以后進行重試。