您的位置:首页 > 数据库 > Mongodb

mongodb 持久化

2015-07-20 10:54 274 查看
上一篇博客中介绍了Journal的功能和监控等内容,我们可以使用journalLatencyTest命令测试刷新journal到磁盘的时间,使用db.serverStatus()查看当前数据库中journal的性能情况。

当系统启动时,mongodb会将数据文件映射到一块内存区域,称之为Shared view,在不开启journal的系统中,数据直接写入shared view,然后返回,系统每60s刷新这块内存到磁盘,这样,如果断电或down机,就会丢失很多内存中未持久化的数据。当系统开启了journal功能,系统会再映射一块内存区域供journal使用,称之为private view,mongodb默认每100ms刷新privateView到journal,也就是说,断电或宕机,有可能丢失这100ms数据,一般都是可以忍受的,如果不能忍受,那就用程序写log吧。这也是为什么开启journal后mongod使用的虚拟内存是之前的两倍。Mongodb的隔离级别是read_uncommitted,不管使用不使用journal,都是以内存中的数据为准,只不过,不开启journal,数据从shared
view读取,开启journal,数据从private view读取。

在开启journal的系统中,写操作从请求到写入磁盘共经历5个步骤,在serverStatus()中已经列出各个步骤消耗的时间。

①、Write to privateView

②、prepLogBuffer

③、WritetoJournal

④、WritetoDataFile

⑤、RemaptoPrivateView

下面详细介绍每个步骤的过程:

流程图:





1、preplogbuffer:

Private view(PV) 中的数据并不是直接刷新到journal文件,而是通过一个中间内存块(journalbuffer,或者alogned buffer)一部分一部分的刷新到journal,这样可以提高并发。preplogbuffer即是将PV中的数据写入到aligned buffer中的过程。这个过程有两部分,basic write 操作和非 basic write操作(e.g.create
file)。一次preplogbuffer是以一个commitJob为一个单位,可能会有很多个commitJob写入到aligned buffer,然后提交。一个commitJob中包含多个basic write 和非basic write 操作,basic write是存在Writeintent结构体中的,Writeintent记录了写操作的地址信息。非basic write 操作存在一个vector中。

具体结构如下。





Aligned buffer 有自己的结构,这也是写入到journalfile中的结构。包含Jheader,JsectHeader lsn,Durop,JSectFooter:





     每个JsectHeader之间的Durop是属于一个事务范围,一起提交,一起成功,一起失败,即all-or-nothing.上篇文章中介绍的lsn文件,就是记录这个lsn号。

2、WritetoJournal:

writetoJournal操作是将alignedbuffer刷新到JournalFile的过程。默认100ms刷新一次,由--journalCommitInterval 参数控制。writetoJournal会做一些checksum验证,将alignedbuffer进行压缩,然后将压缩过后的alignedbuffer写入到磁盘。写入磁盘后将删除已经满的Journal文件,更新lsn号到lsn文件。写操作到这一步就是安全的了,因为数据已经在磁盘上,如果使用getlasterror(j=true),这一步即可返回。

3、WritetoDataFile:

WritetoDataFile是将未压缩的aligned buffer写入到shared view的过程,然后由操作系统刷新到磁盘文件中。WritetoDataFile首先会对aligned buffer进行严格的验证,确保没有改变过,然后解析aligned buffer,通过memcpy函数拷贝到shareview

4、RemaptoprivateView:

RemaptoprivateView会将持久化的数据重新映射到PV,以减小PV的大小,防止它不断扩大,按照源码上说,RemaptoprivateView会两秒钟重新映射一次,大约有1000个view,不是一次全做完,而是一部分一部分的做。由于读操作是读取PV,所以在映射完成之后会有短暂的时间读取磁盘。

经过这四步,一个写操作就完成了,journal提高了数据的安全性,并不像想象中的会丢数据,重要的是如何使用和维护。

以上均参考自mongo官方文档和源码,有理解不对的地方也请大家指正。

参考:

1、journalFormat

2、Dur process steps

3、http://www.mongodb.org/display/DOCS/Durability+Internals

4、源码/src/mongo/db/dur.*
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: