
一、相关概念
JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。
mmap的作用是将硬盘文件的内容映射到内存中,madvise会向内核提供一个针对于于地址区间的I/O的建议,内核可能会采纳这个建议,会做一些预读的操作。
二、RocketMQ
1、HeapByteBuffer、DirectByteBuffer、MappedByteBuffer
在JVM的垃圾回收器里,除了CMS,都是需要移动对象的;如果要把一个Java里的 byte[] 对象的引用传给native代码,让native代码直接访问数组的内容的话,就必须要保证native代码在访问的时候这个 byte[] 对象不能被移动。
在传输数据时(磁盘IO传输和Socket传输都属于fd),如果传入HeapByteBuffer,首先会把HeapByteBuffer 背后的 byte[] 的内容拷贝到一个 DirectByteBuffer,然后再发送DirectByteBuffer中的数据。如果直接使用DirectByteBuffer的话,就会少了一次HeapByteBuffer->DirectByteBuffer
的拷贝。
但是使用DirectByteBuffer也是有代价的,DirectByteBuffer比HeapByteBuffer的创建开销更大,所以如果要使用DirectByteBuffer的话最好还是复用,避免过多的创建。
RocketMQ内部实现基于nio提供的java.nio.MappedByteBuffer,基于FileChannel的map方法得到mmap的缓冲区,会作为page cache的一部分来用
2、DirectByteBuffer和pagecache(MappedByteBuffer)读写分离消息

DirectByteBuffer(堆外内存)+PageCache的两层架构方式,这样子可以实现读写消息分离,写入消息时候写到的是DirectByteBuffer——堆外内存中,读消息走的是PageCache(对于,DirectByteBuffer是两步刷盘,一步是刷到PageCache,还有一步是刷到磁盘文件中),带来的好处就是,避免了内存操作的很多容易堵的地方,降低了时延,比如说缺页中断降低,内存加锁,污染页的回写。
3、Page Cache机制
页面缓存(Page Cache)是Linux内核中针对文件I/O的一项优化,Linux从内存中划出了一块区域来缓存文件页,如果要访问外部磁盘上的文件页,首先将这些页面拷贝到内存中,再进行读写。由于硬件结构限制,磁盘的I/O速度比内存慢很多,因此使用Page cache能够大大加速文件的读写速度。

在page cache占据大量内存前,使用linux内核中提供的posix_fadvise
等缓存管理方法,主动释放掉无用的page cache,来缓解内存压力。
三、jraft
正式提供稳定的 RocksDBSegmentLogStorage,适合 value 较大的数据存储
1、SegmentFile(文件读写io)

具体代码可以参见chenjy16/fileio-contrast具体代码可以参见
https://github.com/chenjy16/fileio-contrast.gitgithub.com