1. 程式人生 > >如何保證RabbitMQ的訊息不丟失及其背後的原理

如何保證RabbitMQ的訊息不丟失及其背後的原理

一、訊息為什麼丟失

RabbitMQ預設情況下的交換機和佇列以及訊息是非持久化的,也就是說在伺服器重啟或者宕機恢復後,之前建立的交換機和佇列都將不復存在,之前未消費的訊息也就消失不見了。原因在於每個佇列和交換機的durable屬性。該屬性預設情況是false,它決定了RabbitMQ是否需要在崩潰或者重啟之後重新建立佇列(或者交換機)。

二、持久化交換機和佇列

將交換機和佇列的durable屬性設定為true,這樣你就不需要在伺服器斷電後重新建立佇列和交換機了。你也許會認為把佇列和交換機的durable屬性設定為true就足夠可以讓訊息倖免於重啟後丟失了,真的是這樣嗎?佇列和交換機當然必須被設定為true,但光這樣做還不夠。
能從AMQP伺服器崩潰中恢復的訊息,我們稱之為持久化訊息。在訊息釋出前,通過把它的“投遞預設”( delivery mode)選項設定為2(AMQP客戶端可能會使用人性化的常量來代替數值)來把訊息標記成持久化。到目前為止,訊息還只是被表示為持久化的,但是它還必須被髮布到持久化的交換機中,併到達持久化的佇列中才行。如果不是這樣的話,則包含持久化訊息的佇列(或者交換機)會在Rabbit崩潰重啟後不復存在,從而導致訊息丟失。

三、持久化訊息

因此,如果訊息想要從Rabbit崩潰中恢復,那麼訊息必須滿足以下條件:
1. 把它的投遞預設選項設定為持久化
2. 傳送到持久化的交換機
3. 到達持久化的佇列

做到以上三點,你就不需要擔心傳送到Rabbit伺服器的訊息因伺服器崩潰等其它原因而丟失了。

四、如何做到訊息持久化的

RabbitMQ確保永續性訊息能從伺服器重啟中恢復的方式是,將它們寫入磁碟上的一個持久化日誌檔案。當釋出一個永續性訊息到持久交換機上時,Rabbit會在訊息提交到日誌檔案後才傳送響應。記住,之後這條訊息如果路由到了非持久佇列的話,它會自動從永續性日誌中移除,並且無法從伺服器重啟中恢復。如果你使用永續性訊息的話,則確保之前提到的永續性訊息的那三點都必須做到位。一旦你從永續性佇列中消費了一個永續性訊息的話(並且確認了它),RabbitMQ會在持久化日誌中把這條訊息標記為等待垃圾收集。在你消費永續性訊息前,如果RabbitMQ重啟的話,伺服器會自動重建交換機和佇列(以及繫結),重播永續性日誌檔案的訊息到合適的佇列或者交換機上(取決於Rabbit伺服器宕機的時候,訊息處在路由過程的哪個環節)。

雖然持久化訊息可以做到訊息的不丟失,但持久化的訊息在進入佇列前會被寫到磁碟,這個過程比寫到記憶體慢得多,所以會嚴重的影響效能,可能導致訊息的吞吐量降低10倍不止。所以,在做訊息持久化前,一定要認真考慮效能和需求之間的平衡關係。