当MongoDB运行在journal开启的状态下, 写操作会在写入磁盘数据文件之前先写入内存和journal文件。本文讨论MongoDB 系统中journaling 的实现和技术细节。更多关于配置、调试、管理journaling的信息见管理Journaling。
(译者注:官方文档并未将journalling机制说清楚,我在白板上画了一幅图来辅助读者理解,在后边的篇幅中会有对这幅图的描述)
Journal 文件
Journaling开启后, MongoDB会在定义好的dbPath路径下创建一个 journal子目录,dbpath路径默认为/data/db。这个目录用来存放journal文件,文件中记录的是write-ahead日志。
(译者注:即WAL,预写式日志。数据库系统在运行时将对数据库的修改写到redo日志中而不是数据文件,然后redo日志通过checkpoint做group commit刷到最终的数据文件里。这是大多数数据库系统采用的做法)
目录下还有一个文件来保存某个最近的序列号。
(译者注:这个文件是journal目录下的lsn文件,里边保存的序列号并非是journal文件的序列号。这个就说来话长了,上边的注释提到写操作在写入数据文件之前会写到journal文件中,而在写入journal文件之前会先写入到一块内存区域,这个内存区域叫private view,官方表示说private view的数据默认每100ms刷到journal文件中,但其实是从private view分批刷到某个临时内存区域,然后从临时内存区域再刷到journal文件,这个刷到临时内存的批次就是lsn文件中保存的序列号)。
一次正常的退出会删除journal目录下所有文件,而一次非正常退出(比如崩溃)则不会;重启mongod进程时会根据journal下的文件来恢复数据以达到数据一致。
Journal文件是append-only文件,文件名以j._为前辍。当超过1G时,MongoDB会创建一个新的文件。一旦某个journal文件的数据全部刷到数据文件之后,MongoDB会删掉这个journal文件,因为它起不到恢复系统的作用了。除非你的系统每秒写入大量数据,否则通常情况下journal目录应该只有两三个文件。
如果你愿意的话,可以在启动mongod进程时设置storage.smallFiles属性,它会将journal文件大小限制到128M。
如果要提高journal文件非常频繁的顺序写入性能,你可以将journal目录放置在和数据文件不同的文件系统下。
重要: 如果将journal和数据文件放置在不同的文件系统中,将不能使用单独使用文件系统快照来备份dbPath目录下的文件。在这种场景下,先使用fsyncLock()来确保数据文件一致性,等快照生成完毕之后使用fsyncUnlock()来释放锁定。 |
注意: 根据你的文件系统的不同,开启journaling第一次启动mongod进程时系统可能会有点滞后,因为要为journal文件预分配空间。 如果mongod进程认为预分配journal文件比在需要时再去创建文件更高效,MongoDB会事先将它分配好。预分配文件的时间可能会持续几分钟,在这段时间内是连接不了数据库的。这是一次性的行为,在以后的调用中不会发生。 |
如果要避免预分配带来的滞后,参见官方文档 Avoid Preallocation Lag。
Journaling中的存储视图
整个Journaling机制中有了3个内部存储视图来服务于MongoDB。
shared view存储修改后的数据然后刷到磁盘的数据文件中。shared view是唯一一个能够直接访问数据文件的视图。当运行时journaling开启,mongod进程会让操作系统将磁盘上所有的数据文件映射到shared view虚拟内存。操作系统只映射文件不会加载真实数据。只有在需要时才会将数据加载到shared view中。
private view中的数据用来响应读操作。private view是一个接收MongoDB写操作的地方。当journal提交后,MongoDB将private view的更改复制到shared view, 这些更改最终通过shared view刷到磁盘数据文件中。
Journal文件是一个基于磁盘的视图,在数据改动刷到磁盘数据文件之前它用来存储private view接收到的写操作。Journal为数据库提供了健壮性,如果 mongod进程在将数据写入到磁盘数据文件之前崩溃了,下次启动时会回放 journal中的写操作到shared view,并最终会将改动刷到磁盘数据文件中。
译者注:官方文档对视图的描述比较简单,这里我对整个持久化流图做了一下梳理,也是对文章开头我画的图的解释。 ① Mongodb启动时将数据文件映射到shared view,这是内存映射,并非加载所有数据。 ② Shared view映射到private view。 ③ Private view通过group commit将客户端的写操作写入到journal文件,其实这中间还经历了一次aligned buffer,官方所说的group commit其实是从aligned buffer到journal文件。 ④ Jaournal文件将写操作回放给shared view。 ⑤ Shared view将数据改动刷到磁盘数据文件。 ⑥ Shared view重新映射到private view。 |
Journaling如何记录写操作
MongoDB将写操作按批次复制到journal文件, 这种方式称之为批量提交。将数据按照“批量提交” 可以有效的减少journaling机制的性能开销,因为每次提交发生时都会阻塞住所有写操作。批量提交的默认时间间隔见commitIntervalMs参数。
Journaling存储的都是原生操作,MongoDB能够利用它们来重放以下操作:
-
文档的插入/更新
-
索引的修改
-
对命名空间元数据进行修改
-
创建和删除数据库,以及一些相关数据文件
当一个写操作发生时,MongoDB将数据写入内存中的private view,然后从private view将写操作分批复制到到journal文件。Journal文件存储在磁盘上以保证健壮性。每条journal数据都描述了写操作让数据文件发生变化的具体地址。
接下来MongoDB将journal中的写操作提交到shared view中,这时shared view和数据文件中的数据会不一致。
默认情况下每隔60秒,MongoDB通过操作系统将shared view的数据改动刷到磁盘上,这样使得最新的写操作能体现在数据文件中。有时操作系统刷磁盘的间隔会超过60秒,特别是在系统空闲内存比较少的时候。
当MongoDB将数据往磁盘上刷时,会记住这些刷过的数据。一旦某个journal文件上记录的所有操作都被刷到数据文件中后,这个文件就再也起不到恢复数据的作用了,MongoDB会删除这个文件,也可能回收它用作一个新的journal文件。
做为整个journaling机制的一部分, MongoDB会照常请求操作系统将shared view重新映射到private view,这样是为了节约物理内存。基于一次新的重映射,操作系统会将物理内存页共享给shared view和private view。
(译者注:shared view初始映射到private view时,private view是只读的,当写操作进来时,mongodb将private view中映射数据的所在页变更为可写,然后从数据文件复制一份真实数据的拷贝,并将写操作的数据写入进来。只有在这时private view才会单独的去消耗内存,初始映射的时候是没有内存消耗的,所以官方说初始时是共享物理内存页)
注意: shared view和磁盘数据文件之间的这部分交互和不使用journaling时大致是一样的, 同样都是MongoDB每隔60秒请求操作系统将内存中的数据改动刷到数据文件中。
|
相关推荐
MongoDB Sharding 机制分析及实现
1.分篇章进行学习,内容控制30分钟内 2.1个月疗程,不要放弃治疗哦 3.图文并茂,有问题请发到邮箱
MongoDB数据库
mongodb集群的认证机制的修改,经过一步一步尝试总结的方法,希望大家看看!
sudo vim /etc/yum.repos.d/mongodb-org-4.2.repo 写入: [mongodb-org-4.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/ gpgcheck=1 enabled=1 gpg...
资源名称:MongoDB应用设计模式内容简介:无论是在构建社交媒体网站,还是在开发一个仅在内部使用的企业应用程序,《MongoDB应用设计模式》展示了MongoDB需要解决的商业问题之间的连接。你将学到如何把MongoDB设计...
一、MongoDB简介 3 二、MongoDB结构 3 二、MongoDB 数据库关系型(这里并不是值关系型数据库的关系) 3 1、MongoDB一对一关系型 3 2、MongoDB一对多关系型 4 3、MongoDB多对多关系型 4 三、创建数据库(mongodb_test...
本课程是一套关于MongoDB应用开发的实战性教程,名为《深入浅出MongoDB应用实战开发(基础、开发指南、系统管理、集群及系统架构)》,教程侧重于讲解MongoDB的常用特性及高级特性,从实际开发的角度出发对MongoDB...
mongodb-triggers是一个轻量级的库,允许实时实时更改通知。 这类似于SQL中的触发器。 可以在Java和JavaScript(MeteorJS)中找到此功能 到底有什么好处呢? 现代应用程序已接近实时响应和更新,这导致要求将数据...
将mongo'DB封装,便于查询 ...支持MongoDB的授权机制(可以使用用户名和密码登录)、支持连接MongoDB副本集、读写分离、安全写入、SSL连接等特性。 内置JFinal和Resty插件。(基于最新版的JFinal和Resty)
mv mongodb-linux-x86_64-4.0.18 mongodb 3、进入 mongodb 目录创建目录 db 和 logs cd /usr/local/mongodb mkdir db mkdir logs 4、进入到 bin 目录下,编辑 mongodb.conf 文件,内容如下: dbpath=/usr/local/...
【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT必备】MongoDB面试题【BAT...
MongoDB图形化管理工具 MongoDB Compass
mongodb-log 是一个基于MongoDB的Python日志系统。 MongoDB 的 Capped Collection是一个天生的日志系统,MongoDB自己的oplog就是用它来存储的,Capped Collection的特点是可以指定Collection的大小,当记录总大小...
MongoDB4.2分片及副本集群搭建 MongoDB集群 MongoDB分片 MongoDB副本 MongoDB副本集群
MongoDB Community Server(mongodb-org-server_5.0.4_amd64.deb)适用于适用于Debian10 MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB是...
MongoDB 学习PPT
MongoDB Community Server(mongodb-src-r5.0.4.tar.gz)源代码 MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB是一个介于关系数据库和非...
教程名称:MongoDB教程基础入门 课程目录:【】MongoDB教程基础入门-代码【】MongoDB教程基础入门01第一讲上【】MongoDB教程基础入门02第一讲下【】MongoDB教程基础入门03第二讲上【】MongoDB教程基础入门04第二讲...
MongoDB Community Server(mongodb-linux-aarch64-ubuntu1804-5.0.8.tgz)适用于Ubuntu 18.04 Arm芯片, MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决...