RocketMQ消息存儲學習

Page Cache

page cache 是 Linux內核實現的磁盤緩存,主要用來減小對磁盤的I/O操做,把磁盤訪問變成物理內存訪問緩存

不管經過標準I/O仍是mmap,首先都是讀入page cache,page cache 內核地址映射到page的物理地址。若是是標準I/O就拷貝到用戶地址,若是是mmap,則將用戶地址映射到相同的page物理地址。
不過mmap只創建了地址映射,因此當進程發起對映射空間訪問時會引起缺頁異常,從而引起磁盤文件到物理內存的拷貝。app

如下參考連接[2]
標準I/O過程:
假設一個名爲render的Linux程序,它打開文件scene.dat並一次讀取512個字節,將文件內容存儲到堆分配的塊中。第一次讀是這樣的: 異步

在這裏插入圖片描述
在讀取了12KB之後,render的堆以及相關的頁幀狀況以下,上面的是page cache,下面的是用戶地址空間對應的物理內存:
在這裏插入圖片描述
mmap 而mmap則直接將render進程的用戶地址空間直接指向了page cache。
在這裏插入圖片描述
page cache 刷盤 page cache修改以後會變成髒頁。
髒頁有兩種刷盤的方式:

  1. 異步刷盤,髒頁太多或者存在過久都會致使page cache回寫磁盤,Linux中能夠經過 sysctl -a | grep dirty 查看相關的控制參數。
  2. 調用fsync、msync等。

RocketMQ消息存儲

RocketMQ文件映射關係
下圖來自Apache RocketMQ 中國開發者釘釘羣陳厚道老師的PPT post

在這裏插入圖片描述
RocketMQ中每一個文件對應一個MappedFile,MappedFile由MappedFileQueue管理。

RocketMQ消息存儲的兩種方式
下圖來自Apache RocketMQ 中國開發者釘釘羣劉春龍老師的PPT 設計

在這裏插入圖片描述
TransientStorePool主要功能是池化管理多個DirectByteBuffer對象,能夠向其借與還Buffer提供給MappedFile使用。
使用DirectByteBuffer的緣由能夠看一下另外一篇文章 《Java直接內存原理》
寫數據
先講一下上圖的第二種的方式:

  • appendMessage直接寫到借來的writeBuffer中,調用commit方法時再經過FileChannel#write()方法寫數據

第一種方式(默認方式):3d

  • 經過FileChannel#map得到的MappedByteBuffer直接寫數據

由上面的Page Cache可知兩種方式操做的是同一塊物理內存(MappedByteBuffer和FileChannel沒有直接關係,即便FileChannel#close(),MappedByteBuffer仍是能夠操做文件)。
讀數據
讀數據只有一種方式,直接經過MappedByteBuffer讀取。
關於刷盤
調用flush會將Page Cache中的數據刷到磁盤。cdn

另外,關於兩種方式,胡宗棠老師的看法。
對象

在這裏插入圖片描述
我的想法

  1. DirectByteBuffer的方式若是掉電會丟失更多的數據。
  2. mmap + pagecache的方式數據更新更及時,畢竟讀數據都是從mmap 讀的。

[1]《Linux內核設計與實現》
[2] manybutfinite.com/post/page-c…
[3] www.quora.com/Linux-Kerne…blog

相關文章
相關標籤/搜索