天天看點

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

RabbitMQ持久化

概念

剛剛我們已經看到了如何處理任務不丢失的情況,但是如何保障當 RabbitMQ 服務停掉以後消息生産者發送過來的消息不丢失。預設情況下 RabbitMQ 退出或由于某種原因崩潰時,它忽視隊列和消息,除非告知它不要這樣做。確定消息不會丢失需要做兩件事: 我們需要将隊列和消息都标記為持久化;

隊列如何持久化

之前我們建立的隊列都是非持久化的,rabbitmq 如果重新開機的化,該隊列就會被删除掉,如果要隊列實作持久化 需要在聲明隊列的時候把 durable 參數設定為持久化;

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

但是需要注意的就是如果之前聲明的隊列不是持久化的,需要把原先隊列先删除,或者重新建立一個持久化的隊列,不然就會出現錯誤;

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

以下為控制台中持久化與非持久化隊列的 UI 顯示區:

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

消息實作持久化

要想讓消息實作持久化需要在消息生産者修改代碼,MessageProperties.PERSISTENT_TEXT_PLAIN 添加這個屬性。

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

将消息标記為持久化但不能完全保證不會丢失消息。盡管它告訴 RabbitMQ 将消息儲存到磁盤,但是這裡依然存在當消息剛準備存儲在磁盤的時候 但是還沒有存儲完,消息還在緩存的一個間隔點。此時并沒有真正寫入磁盤。持久性保證并不強,但是對于我們的簡單任務隊列而言,這已經綽綽有餘了。如果需要更強有力的持久化政策,參考後邊課件釋出确認章節;

不公平分發

在最開始的時候我們學習到 RabbitMQ 分發消息采用的輪訓分發,但是在某種場景下這種政策并不是很好,比方說有兩個消費者在處理任務,其中有個消費者 1 處理任務的速度非常快,而另外一個消費者 2

處理速度卻很慢,這個時候我們還是采用輪訓分發的化就會到這處理速度快的這個消費者很大一部分時間處于空閑狀态,而處理慢的那個消費者一直在幹活,這種配置設定方式在這種情況下其實就不太好,但是

RabbitMQ 并不知道這種情況它依然很公平的進行分發;

為了避免這種情況,我們可以設定參數 channel.basicQos(1);

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化
RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化
RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化

意思就是如果這個任務我還沒有處理完或者我還沒有應答你,你先别配置設定給我,我目前隻能處理一個任務,然後 rabbitmq 就會把該任務配置設定給沒有那麼忙的那個空閑消費者,當然如果所有的消費者都沒有完成手上任務,隊列還在不停的添加新任務,隊列有可能就會遇到隊列被撐滿的情況,這個時候就隻能添加新的 worker 或者改變其他存儲任務的政策。

預取值

本身消息的發送就是異步發送的,是以在任何時候,channel 上肯定不止隻有一個消息另外來自消費者的手動确認本質上也是異步的。是以這裡就存在一個未确認的消息緩沖區,是以希望開發人員能限制此緩沖區的大小,以避免緩沖區裡面無限制的未确認消息問題。這個時候就可以通過使用 basic.qos 方法設定“預取計數”值來完成的。==該值定義通道上允許的未确認消息的最大數量。==一旦數量達到配置的數量,RabbitMQ 将停止在通道上傳遞更多消息,除非至少有一個未處理的消息被确認,例如,假設在通道上有未确認的消息 5、6、7,8,并且通道的預取計數設定為 4,此時 RabbitMQ 将不會在該通道上再傳遞任何消息,除非至少有一個未應答的消息被 ack。比方說 tag=6 這個消息剛剛被确認 ACK,RabbitMQ 将會感覺這個情況到并再發送一條消息。消息應答和 QoS 預取值對使用者吞吐量有重大影響。通常,增加預取将提高向消費者傳遞消息的速度。==雖然自動應答傳輸消息速率是最佳的,但是,在這種情況下已傳遞但尚未處理的消息的數量也會增加,進而增加了消費者的 RAM 消耗(随機存取存儲器)==應該小心使用具有無限預處理的自動确認模式或手動确認模式,消費者消費了大量的消息如果沒有确認的話,會導緻消費者連接配接節點的記憶體消耗變大,是以找到合适的預取值是一個反複試驗的過程,不同的負載該值取值也不同 100 到 300 範圍内的值通常可提供最佳的吞吐量,并且不會給消費者帶來太大的風險。預取值為 1 是最保守的。當然這将使吞吐量變得很低,特别是消費者連接配接延遲很嚴重的情況下,特别是在消費者連接配接等待時間較長的環境中。對于大多數應用來說,稍微高一點的值将是最佳的。

RabbitMQ學習(三)-- 隊列持久化RabbitMQ持久化