1. 程式人生 > >RabbitMQ持久化機制

RabbitMQ持久化機制

之前其實已經寫過一篇關於RabbitMQ持久化的 文章 ,但那篇文章側重程式碼層面的寫入流程,對於持久化操作何時發生以及什麼時候會重新整理到磁碟等問題其實都沒有搞清楚,這篇文章著重於關注這些問題。

訊息什麼時候需要持久化?

根據 官方博文 的介紹,RabbitMQ在兩種情況下會將訊息寫入磁碟:

  1. 訊息本身在publish的時候就要求訊息寫入磁碟;
  2. 記憶體緊張,需要將部分記憶體中的訊息轉移到磁碟;

訊息什麼時候會刷到磁碟?

  1. 寫入檔案前會有一個Buffer,大小為1M(1048576),資料在寫入檔案時,首先會寫入到這個Buffer,如果Buffer已滿,則會將Buffer寫入到檔案(未必刷到磁碟);
  2. 有個固定的刷盤時間:25ms,也就是不管Buffer滿不滿,每隔25ms,Buffer裡的資料及未重新整理到磁碟的檔案內容必定會刷到磁碟;
  3. 每次訊息寫入後,如果沒有後續寫入請求,則會直接將已寫入的訊息刷到磁碟:使用Erlang的receive x after 0來實現,只要程序的信箱裡沒有訊息,則產生一個timeout訊息,而timeout會觸發刷盤操作。

訊息在磁碟檔案中的格式

訊息保存於$MNESIA/msg_store_persistent/x.rdq檔案中,其中x為數字編號,從1開始,每個檔案最大為16M(16777216),超過這個大小會生成新的檔案,檔案編號加1。訊息以以下格式存在於檔案中:

<<Size:64, MsgId:16/binary, MsgBody>>

MsgId為RabbitMQ通過rabbit_guid:gen()每一個訊息生成的GUID,MsgBody會包含訊息對應的exchange,routing_keys,訊息的內容,訊息對應的協議版本,訊息內容格式(二進位制還是其它)等等。

檔案何時刪除?

當所有檔案中的垃圾訊息(已經被刪除的訊息)比例大於閾值(GARBAGE_FRACTION = 0.5)時,會觸發檔案合併操作(至少有三個檔案存在的情況下),以提高磁碟利用率。

publish訊息時寫入內容,ack訊息時刪除內容(更新該檔案的有用資料大小),當一個檔案的有用資料等於0時,刪除該檔案。