MongoDB的Journal

来源:互联网 发布:淘宝产品搜索排名 编辑:程序博客网 时间:2024/06/05 20:36

MongoDB采用提前写日志到磁盘日志文件的方式来实现发生故障时的数据持久化。
Journal是一个连续的、二进制的事务日志,在突然停机时,我们用它来恢复数据库到一个有效的状态。
下面分别介绍Journaling在三种不同存储引擎下的作用。

一、WiredTiger
WiredTiger使用检查点来为磁盘上的数据提供一个一致性的试图,允许MongoDB从上一个检查点恢复数据。然而,如果MongoDB在两个检查点之间意外退出,则会丢失两个检查点之间的数据。此时我们需要用Journaling来恢复最后一个检查点之后产生的信息。
1、使用journaling,恢复数据的步骤如下:

(1) 在数据文件中查找最后一个检查点的标识;
(2) 在journal文件中搜索匹配最后一个检查点标识的记录;
(3) 应用journal文件中从最后一个检查点之后的所有操作。

2、日志记录的过程(Journaling Process)
WiredTiger 为每一个客户端创建一个journal记录来初始化写操作。例如,更新集合中的一个文档会造成索引的修改,WiredTiger 会创建一条单独journal,该条journal中包含更新操作和与它关联的索引的修改信息。
MongoDB配置WiredTiger使用内存缓冲来存储journal记录。使用线程协调来分配和拷贝到缓冲的部分。所有大于128KB的journal记录会被缓冲。
WiredTiger 同步*缓冲的journal记录磁盘*根据以下的时间间隔或者条件:

(1) 在3.2版本中,每50毫秒同步一次
(2) MongoDB设置WiredTiger存储引擎创建检查点的时机有两个:一个是在每60秒的时候,另一个是journal文件中已经写入了2GB的数据。二者中哪一个先发生都会开始创建检查点。
(3) 如果写操作包含一个写关心j: true,那么WiredTiger会强制一次journal 文件同步。
(4) 因为MongoDB有100MB journal文件的限制,WiredTiger 会创建一个新的journal文件近似100MB数据,当创建了一个新的journal文件之后,WiredTiger会同步之前的journal文件。

注意:当在写操作之间发生突然停机的话,保存在WiredTiger缓存中的更新会丢失。

3、日志文件(Journal Files)
开启journaling的情况下,MongoDB会在dbpath下创建一个叫做journal 的子目录,WiredTiger的journal文件的名字格式为WiredTigerLog.,其中是一个用0填充的数字,从0000000001开始。
journal文件中包含对应每一次写操作的一条记录,每条记录都有唯一的标识符。WiredTiger 最小的日志记录大小是128字节,如果记录小于128字节,则不会对其压缩。
WiredTiger 会自动移除老的journal文件,并且仅维护从最后一个检查点恢复数据时所需的journal文件。

二、MMAPv1
使用MMAPv1存储引擎,当写操作发生时,MongoDB会更新内存中的视图。在journaling开启时,MongoDB首先将内存中的改变写入到磁盘上的journal文件中。如果在将数据提交到数据文件之前发生发生终止或错误,MongoDB会使用journal文件将写操作应用到数据文件中,以此来维护一个一致的状态。
1、日志记录的过程(Journaling Process)
使用journaling,MongoDB的存储层有两个关于数据集的内部视图,分别是用于写入journal文件私有视图和用于写入数据文件共享视图

(1) MongoDB首先将写操作应用于私有视图
(2) 然后,MongoDB以大约100毫秒的时间间隔将私有视图中的更改应用到日志目录中的磁盘journal文件中。MongoDB成批地将写操作记录到磁盘上的journal文件的操作叫做组提交。这样做的目的是为了最小化对journaling的性能影响,因为这些提交必须在提交期间阻塞所有的写入器。写入journal文件具有原子性。
(3) 一经journal提交,MongoDB 会将journal中的所有改变应用到共享视图中去。
(4) 最后,MongoDB将共享视图中的改变应用到数据文件中,更准确的说是,每隔60秒,MongoDB 会让操作系统刷新共享视图中的数据到数据文件。操作系统有可能会以比60秒更高的频率去刷新共享视图中的数据到数据文件,尤其是当系统内存比较小的时候。
MongoDB共享视图与磁盘上数据文件的交互方式与在不开启journaling时MongoDB的工作方式类似。不开启journaling的时候,MongoDB让操作系统每隔60秒将内存中数据的变化刷新到到磁盘的数据文件中。

2、日志文件(Journal Files)
开启journaling的情况下,MongoDB会在dbpath下创建一个叫做journal 的子目录,journal 目录下包含一些命名格式为j._的journal文件,其中从整数0开始,还包含一个“last sequence number” 文件lsn。
Journal 文件包含提前写日志;每一个journal条目描述写操作在数据文件中改变的字节数。Journal 文件是只追加文件。每当一个journal文件达到1GB,MongoDB 都会创建一个新的journal文件。如果启动数据库实例mongod的时候使用storage.smallFiles参数,则限制每一个journal文件的大小为128 megabytes(百万字节,近似于MB)
lsn文件中保存着最后一次刷新数据到数据文件的时间。
一旦MongoDB 将某个特定journal文件中的写操作写入数据文件后,MongoDB可以将它用于一个新的journal文件。
除非你每秒写很多数据,否则journal目录下将仅有两到三个journal 文件。
干净的关机会移除journal目录下的所有文件,脏关机会将journal文件留在journal目录下。这些文件会被用在重启时自动将数据库恢复数据到一个一致的状态。

3、日志目录(Journal Directory)
为了加快当前journal文件的频繁连续写入,你可以确保journal目录与数据库数据文件不在一个文件系统下。
注意:如果你将journal与数据文件放在不同的文件系统下,您不能仅使用文件系统快照来捕获dbPath目录的有效备份。在这种情况下,使用fsyncLock()以确保在快照之前数据库文件是一致的,使用fsyncUnlock() 一旦快照完成。
4、预先分配延迟(Preallocation Lag)
MongoDB 也许会预先分配journal文件如果mongod认为这样做比需要的时候再分配更加有效。
根据你的文件系统,你可能会在第一次启动一个带有journaling 的mongod实例时经历一个预先分配的延迟。预分配的时间有可能会持续几分钟,在此期间,我们将连接不到数据库,这是一次性的预分配,不会在将来的调用中发生。
避免预分配延迟的方法
你可以通过拷贝其他mongod实例的预分配文件来预分配该实例下的journal文件。预分配文件不包含数据。以后把它们移走是安全的。但是如果你用journaling重启数据库实例,数据库实例会再一次创建它们。

三、In-Memory
从MongoDB企业版本3.2.6开始,内存存储引擎成为通用版本的一部分。由于它的数据存储在内存中,所以没有单独的journal,带有写关心j的写操作会被立即确认。如果副本集中的任何一个成员没有开启journaling功能,那必须设置writeConcernMajorityJournalDefault为false。

原创粉丝点击