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分鐘之內沒有支付成功,那麼訂單就會自動取消。除了延遲消費,延遲佇列的典型應用場景還有延遲重試。比如消費者從佇列裡面消費訊息失敗了,可以延遲一段時間以後進行重試。