mongoDB研究笔记:journaling保证意外故障下的数据完整性

mongoDB的Journaling日志功能与常见的log日志是不一样的,mongoDB也有log日志,它只是简单记录了数据库在服务器上的启动信息、慢查询记录、数据库异常信息、客户端与数据库服务器连接、断开等信息。Journaling日志功能则是mongoDB里面非常重要的一个功能,它保证了数据库服务器在意外断电、自然灾害等情况发生下数据的完整性。尽管mongoDB还提供了其它的复制集等备份措施(后面会分析),但Journaling的功能在生产环境中是不可缺少的,它依靠了较小的CPU和内存消耗,带来的是数据库的持久性和稳定性。本篇章将分析Journaling涉及到的功能细节问题。Journaling的工作流程?

 几个重要的存储视图

Journaling功能用到了两个重要的内存视图:private view和shared view。这两个内存视图都是通过MMAP(内存映射)来实现的,其中对private view的映射的内存修改不会影响到磁盘上,shared view中数据的变化会影响到磁盘上的文件,系统会周期性的刷新shared view中的数据到磁盘。

(1) shared view在mongoDB启动的过程中,操作系统会将磁盘上的数据文件映射到内存中的shared view,操作系统只是完成映射,并没有立即加载数据到内存,mongoDB会根据需要加载数据到shared view。

(2)private view 内存视图是为读操作保存数据的位置,是mongoDB保存新的写操作的第一个地方。

(3)磁盘上的Journaling日志文件,是实现写操作持久化保存的地方。mongoDB实例启动时会读这个文件。

 处理写操作的流程

     当写操作发生时,mongoDB首先将数据写到内存中的private view处,然后将写操作批量复制到journal,journal会将写操作存储到磁盘上的文件上,使其持久化保存,journal日志文件上的每一个条目都描述了写操作更改了数据文件上的哪些字节。

     当上面的步骤完成后,mongoDB接下来会利用journal日志中的写操作记录来更新shared view中的数据,此时内存中的数据与磁盘上的数据变得不一致。按照默认值60秒,mongoDB会周期性的要求操作系统将shared view中变化的数据刷新到磁盘上,使磁盘上的数据与内存中的数据保持一致。

当执行完刷新内存中变化的数据到磁盘后,mongoDB会删除掉journal中这个时间点后面的所有写操作。

最后,mongoDB会将shared view与private view重新同步,保持一致性。

mongoDB的journaling日志功能,在2.0版本后是默认启动的,可以在实例mongod启动时,通过启动选项控制;上面提到的步骤中,有一个地方是将写操作周期性批量写到journal日志文件中,这个周期的大小是通过可选启动参数journalCommitInterval来控制的,默认值是100ms。

mongoDB经过60s的周期刷新内存中变化的数据到磁盘,这个值通过启动可选参数syncdelay来控制的。这些默认值一般适用于大多数情况,不要轻易更改。通过上面的分析,数据库服务器仍然有100ms的丢失数据的风险,因为journaling日志的写到磁盘上的周期是100ms,假如刚好一批写操还在内存中,没来得及刷到journaling在磁盘上对应的文件上,服务器突然故障,这些在内存中的写操作就会丢失。

mongoDB在启动时,专门初始化一个线程不断循环,用于在一定时间周期内来从defer队列中获取要持久化的数据并写入到磁盘的journal(日志)和mongofile(数据)处,当然因为它不是在用户添加记录时就写到磁盘上,所以按mongodb开发者说,它不会造成性能上的损耗,因为看过代码发现,当进行CUD操作时,记录(Record类型)都被放入到defer队列中以供延时批量(group commit)提交写入。 

总之mongoDB利用内存映射的技术来完成这些功能,需要参考unix环境编程中的内存映射MMAP,文件IO等编程知识。

posted @ 2013-09-08 11:52  郭远威  阅读(1850)  评论(0编辑  收藏  举报