`
shingo7
  • 浏览: 19361 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

MongoDB Journaling 机制

阅读更多

当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入门指南.pdf

    MongoDB中的Journaling是指将数据库的操作日志记录到磁盘上,以便在系统崩溃时可以快速地恢复数据。MongoDB的原子性和事务机制可以确保数据的一致性。 MongoDB的应用场景包括: 1.大数据处理:MongoDB可以处理...

    MongoDB面试专题.pdf

    MongoDB默认不使用传统的锁或复杂的事务处理机制,而是提供了一种类似MySQL MyISAM的自动提交模式,这有助于提高性能。 在32位系统上,MongoDB默认禁用了journaling功能,以避免额外的内存映射文件进一步限制数据库...

    2021Java字节跳动面试题——面向字节_MongoDB.pdf

    - 在32位系统上,MongoDB默认禁用了journaling功能,这是因为journaling会占用额外的内存资源,从而限制了32位系统上的最大数据库大小。 #### 知识点七:MongoDB的安全备份与恢复 - MongoDB支持多种备份策略,包括...

    Mongodb存储特性与内部原理

    在实际应用中,为保证数据的一致性和持久性,MongoDB 使用了这种机制。写入操作首先记录在 journal 中,然后再更新数据文件。这样,即使发生故障,系统也可以通过重放 journal 中的操作来恢复数据。 通过使用 db....

    MongoDB Architecture Guide

    此外,MongoDB还使用写前日志(Journaling)来提高数据的安全性。 在性能方面,MongoDB能够利用内存性能,并同时具备磁盘容量。这种设计既保证了快速的数据访问速度,也确保了在大数据量下的存储能力。它为构建大...

    JAVA_MongoDB面试专题.pdf

    7. MongoDB的journaling确保了数据一致性,不完整的journal条目在恢复时不会被回放,保证了数据的安全性。 8. 分析器在MongoDB中用于评估查询性能,帮助开发者识别慢查询并优化数据库。 9. 名字空间是MongoDB中的...

    MongoDB面试专题及答案.pdf

    在32位系统上,MongoDB默认禁用日志(journaling),因为journaling会激活额外的内存映射文件,进一步限制数据库大小。而在故障恢复时,MongoDB会确保只有完整的一致性日志组才会被回放,以保证数据的完整性。 ...

    大数据存储MongoDB实战指南1

    - 数据持久化通过日志机制实现,即Journaling,确保在系统崩溃后能够恢复未完成的事务。 - **应用实践**: - 本书通过一系列经典案例,展示了如何在大数据环境中有效使用MongoDB进行数据存储和管理。 - 特别强调...

    MongoDB0526 讲义-预习.pdf

    在MongoDB中,WiredTiger的工作流程包括Journaling,即在写操作发生时先将数据写入日志,然后异步写入数据文件。在系统崩溃后,可以通过检查点和日志恢复未完成的操作,保证数据完整性。 MongoDB的高可用性主要通过...

    《MongoDB实战》第2版-目录1

    本章主要涵盖了MongoDB的关键特性,包括它的文档数据模型、查询机制、索引、复制、加速与持久化以及伸缩性,这些都是理解MongoDB核心功能的基础。 1. 为互联网而生:MongoDB设计之初就着眼于互联网应用的需求,提供...

    深入了解MongoDB是如何存储数据的

    此外,MongoDB还支持日志记录(Journaling),用于提高数据的安全性和一致性。当journal功能启用时,MongoDB会在每次写操作前将数据写入journal文件,即使在系统崩溃或异常关闭后,也能通过journal恢复未完成的事务...

    mongodb:MongoDB

    在数据持久性方面,MongoDB提供了多种机制来确保数据安全。首先,日志记录(Journaling)功能可以在系统崩溃时恢复未完成的写操作,保证数据一致性。此外,MongoDB还支持自动备份和恢复,可以通过`mongodump`和`...

Global site tag (gtag.js) - Google Analytics