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

相关文章
相关标签/搜索