存储文件内存映射-MappedFile|学习笔记

简介: 快速学习存储文件内存映射-MappedFile

开发者学堂课程【RocketMQ 知识精讲与项目实战(第三阶段)存储文件内存映射-MappedFile】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/704/detail/12481


存储文件内存映射-MappedFile

 

内容介绍:

一.重要属性

二.初始化方式

三.MappedFile 提交

 

一.重要属性

MappedFile 就是 MappedFileQueue  中的每一个队列中的元素,这个类对应的是 CommitLog 中的每一个文件,这个类中重要属性信息如下:

1.int OS_PAGE_SIZE = 1024*4;

//操作系统每页大小,默认4k

刷盘时如果当前每页数据达到1024*4,可以开始给下一页写数据。

2.AtomicLong TOTAL_MAPPED_VIRTUAL_MEMORY = new AtomicLong(0);

//当前JVM实例中 MappedFile 虚拟内存的大小

3.AtomicInteger TOTAL_MAPPED_FILES = new AtomicInteger(0);

//当前JVM实例中 MappedFile 对象个数

4.AtomicInteger wrotePosition = new AtomicInteger(0);

//当前文件的写指针

5.AtomicInteger committedPosition = new AtomicInteger(0);

//当前文件的提交指针

6.AtomicInteger flushedPosition = new AtomicInteger(0);

//刷写到磁盘指针

7.int fileSize;

//文件大小

默认都是1G

8.FileChannel fileChannel;

//文件通道

9.ByteBuffer writeBuffer = null;

//堆外内存 ByteBuffer

writeBuffer 是否能够使用取决于 transientenable 控制,如果支持堆外内存缓存区的开启,这指的是堆外内存的空间

10.TransientStorePool transientStorePool = null;

//堆外内存池

堆外内存数据通过 transientStorePool 对象产生堆外内存区域

11.String fileName;

//文件名称

12.long fileFromOffset;

//该文件的处理偏移量

13.File file;

//物理文件

14.MappedByteBuffer mappedByteBuffer;

//物理文件对应的内存映射 Buffer

15.volatile long storeTimestamp = 0;

//文件最后一次内容写入时间

16.boolean firstCreateInQueue = false;

//是否是 MappedFileQueue 队列中第一个文件的标识,默认是false

 

二.初始化方式

image.pngMappedFile 中有两个 init 方法,这两个方法其实是初始化方法。这两个 init 方法的区别

image.png一个是直接就是文件名称,文件大小

另一个重载的方法有文件名称,文件大小,还有一个transientStorePool 存储池的类。

有两种初始化方式是因为与 transientStorePoolEnable 属性有关,该属性如果开启之后,数据先存储到堆外内存中,然后再通过Commit 线程将数据提交到内存映射的方法中,再通过Flush线程将内存映射当中的 Buffer 数据持久化磁盘。所以这两种初始化方式最明显的区别就是数据看直接提交到内存映射中还是先刷写到堆外内存,然后再提交到MappedByteBuffer中。基于MappedByteBuffer,要开启该特征,就会有两种初始化方式。

 

三. MappedFile 提交

当数据提交到 FileChannel 之后,commitLeastPages 就为本次提交的页数,如果待提交的数据不满足本次最小提交页数,则不执行本次提交操作。当前 writeBuffer 如果为空,就没有提交这一说,对应图如下

image.png

在提交时必须满足当前提交的页数必须大于最小页数,才会出发提交的事件。如果当前能够提交,就会进入 commit0 方法提交数据。判断是否能够提交有一个 isAbleToCommit 方法,首先拿到刷盘的指针以及当前文件写的指针,然后判断如果设定了commitLeastPages,如果其大于0,需要通过分页的方式提交,计算了当前写入到 writeBuffer 中的数据与上一次刷盘的数据进行差值的比较,然后根据每一页数据量的大小计算总页数,总页数大于最小提交的页数,则直接提交。如果 commitLeastPages 小于0,如果有新数据,则直接出发提交。为了提高数据提交的性能,一般都会设计最小提交的页数。如果达到了提交条件,通过 commit0 方法进行出发然后提交。如果开启了堆外内存的共享区,会先将数据通过writeBuffer 提交到 fileChannel,如果没有 writeBuffer,则直接等待刷盘。当前提交位置的设定,commit0 方法的作用是将MappedFile中的writeBuffer中的数据提交到文件通道FileChannel 中。

接下来出发刷盘,刷写磁盘直接调用 MappedByteBuffer 或者fileChannel 中的 force 方法将内存中的数据刷写至磁盘。刷盘的位置应该等于 MappedByteBuffer 中的写指针,如果 writeBuffer不为空,也就是现在开启了堆外内存的共享区,那么刷盘的位置应该等于上一次提交的数据,因为提交的数据最终也需要刷写至磁盘中,所以根据 writeBuffer 是否存在,刷盘位置存在区别。可以根据位置查找指定的 MappedBuffer。

此外还有重要的方法 shutdown, MappedFile 文件销毁通过该方法进行。

public void shutdown(final long intervalForcibly) {

if (this.available) {

//关闭 MappedFile

this.available = false;

//设置当前关闭时间戳

this.firstShutdownTimestamp = System.currentTimeMillis();

//释放资源

this.release();

}else if (this.getRefCount() > 0) {

if ((System.currentTimeMillis() - this.firstShutdownTimestamp) >= intervalForcibly) {

this.refCount.set(-1000 -this.getRefCount());

this.release();

}

}

}

以上就是关于 MappedFile 简单的说明,主要明白几个事情。第一MappedFile 这个类对应的是 CommitLog中的每一个数据文件,MappedFile 在进行初始化时,有两种方式,第一种如果开启了堆外内存,要将堆外内存的区域初始化,如果没有开启堆外内存,直接创建对应的 MappedByteBuffer 内存映射的区域。根据是否开启堆外内存,刷盘有两种途径,第一种途径开启了堆外内存,数据先写入writeBuffer,然后再提交到 fileChannel, fileChannel 也是根据内存映射产生的。如果没有开启堆外内存,则直接写入内存文件映射中,然后刷到磁盘,这是二者最大的区别。

相关文章
|
27天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
44 6
|
2月前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
116 1
|
2月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
2月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
2月前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
45 4
|
2月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
61 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
2月前
|
存储 机器学习/深度学习 人工智能
数据在内存中的存储
数据在内存中的存储
|
2月前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储
|
2月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
65 0
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
273 1