This was originally posted to Kristina Chodorow’s blog, Snail in a Turtleneck
我参与编写了The Definitive Guide中关于Journaling的部分,但是我意识到其中很多实现细节大家重视的不够,所以这次在博客里我会用易于理解的图来进行说明。
那么Journaling是怎么工作的呢,假设如图所示,你的硬盘上有数据文件和日志文件
当你启动mongod,它会映射你的数据文件到一个共享的视图中,比方说操作系统会把你 2,000 bytes的数据文件映射到内存地址1,000,000-1,002,000中,这样你访问 1,000,042这个地址也就是访问这个文件的第42位地址。(其实就是内存映射。。。)。当然,实际上只有第一次真正访问的时候,这个数据文件才会加载到内存中。
如果你改变了内存中的数据,操作系统会刷新变更到实际的文件中去。mongodb在没有开启journaling情况下每60秒由操作系统进行一次刷新。如果开启了journaling,mongod将会映射另外一个私有的视图,这也就是为什么开启journaling的情况下虚拟内存使用量翻番的原因。
现在每次写入共享视图的同时也会写入到私有的视图中。需要注意的是,因为这个私有的视图没有映射到实际文件中,所以操作系统每次刷新时不会把私有视图的变更写回到硬盘。
mongod会向journal file写入关于是是哪个文件的哪个字节发生了变化的简要描述信息。
会向journal file追加每一次变更信息。
如果mongod发生崩溃的时候数据变更还没有写入磁盘,就可以通过回放journal里的记录到共享视图中。
回放成功后,mongod会依赖操作系统把刷新变更刷新到磁盘文件中。默认情况下是60秒一次。
最后mongod会重新映射共享视图到私有视图中。这是为了防止私有视图变的太“脏”(其实也就是为了防止下次在回放的时候写入多余的变更)。