RabbitMQ:5、高階

存儲機制

持久化的消息和非持久化的消息均可以被寫入到磁盤。
持久化的消息一開始就會寫入磁盤,若是能夠,也會在內存中保存一部分以提升性能,當內存吃緊時會從內存中清楚。
非持久化的消息通常存儲在內存中,內存吃緊時會換入到磁盤中,以節省內存空間。
這兩種類型的消息的落盤處理都在RabbitMQ的」持久層「完成。算法

持久層

持久層是一個邏輯概念,包含隊列索引和消息存儲。性能

  • 隊列索引(每一個隊列一個):rabbit_queue_index 負責維護隊列中落盤消息的信息,包括消息的存儲地點、是否己被交付給消費者、是否己被消費者 ack 等。
    rabbit_queue_index 中以順序(文件名從0開始累加)的段文件來進行存儲,後綴爲" . idx " ,每一個段文件中包含固定的 SEGMENT_ENTRY_COUNT 條記錄,SEGMENT-ENTRY-COUNT 默認值爲 1638 。每一個 rabbit_queue_index 從磁盤中讀取消息的時候至少要在內存中維護一個段文件,因此設置 queue_index_embed_msgs_below(存儲在哪一個結構的臨界值) 值的時候要格外謹慎 一點點增大也可能會引發內存爆炸式的增加。
  • 消息存儲(每一個節點有且只有一個):rabbit_msg_store 以鍵值對的形式存儲消息,它被全部隊列共享。
    通過 rabbit_msg)store 處理的全部消息都會以追加的方式寫入到文件中,當這個文件的大小超過指定的限制(file_size_limit)關閉這個文件再建立一個新的文件以供新
    的消息寫入。文件名(文件後綴是". rdq") 開始進行累加 所以文件名最小的文件也是最老的文件。在進行消息的存儲時, bb 會在 ETS(Erlang Term Storage)表中記錄消息
    在文件中的位置映射(Index)和文件的相關信息( FileSummary)。

消息能夠存儲在rabbit_queue_index中,也能夠存儲在在rabbit_msg_store中。最佳的配備是較小的消息存儲在 rabbit queue index 中而較大的消息存儲在rabbit_msg_store 中。索引

隊列的結構

隊列一般由rabbit_amqqueue_process和backing_queue兩部分組成隊列

  • rabbit_amqqueue_process:負責協議相關的消息處理
  • backing_queue:消息存儲的具體形式和引擎

惰性隊列

儘量地將消息存入磁盤中,在消費者消費到相應消息時才被加載到內存中。進程

內存和磁盤告警

內存或者磁盤低於配置的閾值時,RabbitMQ會暫時阻塞客戶端的鏈接直至恢復正常。blocking:對應消費者關聯的connection,這時候並不阻塞。blocked:對應發送消息的Connection,這時候阻塞。內存

流控

RabbitMQ從2.8版本之後還引入了流控來保證系統的穩定性。內存和磁盤告警至關於全局流控,一旦觸發會阻塞集羣中全部Connection,本流控是針對單個Connection的。
RabbitMQ 使用了一種基於信用證算法 (credit-based algorithm) 的流控機制來限制發送消息的速率以解決前面所提出的問題。
流控做用於Connection,出現郵件飽和時會阻塞。流控做用於Channel,出現性能瓶頸時會阻塞。it

解決性能瓶頸

綜上,瓶頸每每發生在rabbit_amqqueue_process 中,用多個rabbit_amqqueue_process代替單個rabbit_amqqueue_process,能夠充分利用上被流控的性能(聲明交換器、隊列、綁定關係;封裝消費者;封裝生產者)。io

鏡像隊列

避免單點問題,集羣中某個節點崩潰,雖然交換器和綁定關係還能保存,隊列和其上存儲的消息卻不能倖免於難,這是由於隊列進程及其內容僅僅維持在
單個節點之上,因此一個節點的失效表現爲其對應的隊列不可用。
引入鏡像隊列的機制,能夠將隊列鏡像到集羣中的其餘 Broker 節點之上,若是集羣中的一個節點失效了,隊列能自動地切換到鏡像中的另外一個節點上以保證服務的可用性。集羣

相關文章
相關標籤/搜索