mongodb内存映射原理

 

内存映射

mongodb非常吃内存,为啥这么吃内存呢,mongodb使用的是内存映射存储引擎,即Memory Mapped Storage Engine,简称MMAP,MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,把磁盘IO操作转换成内存操作。 avatarmapped:映射到内存的数据大小, vsize:虚拟内存,是mapped的2倍 这里虚拟内存是mapped的两倍,是因为我们开启了Journal日志,需要在内存中多映射一次,大概就是它的两倍了。如果关闭Journal日志,虚拟内存大小将和mapped大小相当。

原理

内存映射,是把文件中数据全部映射到内存中的吗?还是只是映射一部分内容,那么这部门内容又是如何确定呢?看这张图 avatar

映射了就不需要读磁盘吗,没有磁盘IO吗? 没有内存映射会怎么样 进程调用read,write的系统调用函数,内核进程把磁盘的数据读到内核空间,然后在copy到用户进程空间。没错,就是两次复制。

而有了内存映射之后,用户进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。

总而言之,常规文件操作需要从磁盘到页缓存再到用户主存的两次数据拷贝。而mmap操控文件,只需要从磁盘到用户主存的一次数据拷贝过程。说白了,mmap的关键点是实现了用户空间和内核空间的数据直接交互而省去了空间不同数据不通的繁琐过程。因此mmap效率更高。

两步走

  • 内存映射

在内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了内存,这个过程由系统调用mmap()实现,所以建立内存映射的效率很高。 avatar

  • 缺页中断

既然建立内存映射没有进行实际的数据拷贝,那么进程又怎么能最终直接通过内存操作访问到硬盘上的文件呢?那就要看内存映射之后的几个相关的过程了。

mmap()会返回一个指针ptr,它指向进程逻辑地址空间中的一个地址,这样以后,进程无需再调用read或write对文件进行读写,而只需要通过ptr就能够操作文件。但是ptr所指向的是一个逻辑地址,要操作其中的数据,必须通过内存管理单元MMU将逻辑地址转换成物理地址,如图1中过程2所示。这个过程与内存映射无关。

前面讲过,建立内存映射并没有实际拷贝数据,这时,MMU在地址映射表中是无法找到与ptr相对应的物理地址的,也就是MMU失败,将产生一个缺页中断,缺页中断的中断响应函数会在swap中寻找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则会通过mmap()建立的映射关系,从硬盘上将文件读取到物理内存中,如图1中过程3所示。这个过程与内存映射无关。

如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘上,如图1中过程4所示。这个过程也与内存映射无关。

所以当mongodb读取数据库文件的时候,首先做内存映射,读取文件变成了读取内存操作,所以mongodb的查询效率相当高,当然,如果你的内存不够大,经常发生缺页中断,那么效率会大打折扣了

Mongodb学习整理之内存映射机制

认真分析mmap:是什么 为什么 怎么用

从内核文件系统看文件读写过程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章