mongodb 持久化(5)

默北 mongodbmongodb 持久化(5)已关闭评论14,4071字数 2225阅读7分25秒阅读模式

当系统启动时,mongodb会将数据文件映射到一块内存区域,称之为Shared view,在不开启journal的系统中,数据直接写入shared view,然后返回,系统每60s刷新这块内存到磁盘,这样,如果断电或down机,就会丢失很多内存中未持久化的数据。

当系统开启了journal功能,系统会再映射一块内存区域供journal使用,称之为private view,mongodb默认每100ms刷新privateView到journal,也就是说,断电或宕机,有可能丢失这100ms数据,一般都是可以忍受的,如果不能忍受,那就用程序写log吧。这也是为什么开启journal后mongod使用的虚拟内存是之前的两倍。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

Mongodb的隔离级别是read_uncommitted,不管使用不使用journal,都是以内存中的数据为准,只不过,不开启journal,数据从shared view读取,开启journal,数据从private view读取。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

在开启journal的系统中,写操作从请求到写入磁盘共经历5个步骤,在serverStatus()中已经列出各个步骤消耗的时间。
①、Write to privateView
②、prepLogBuffer
③、WritetoJournal
④、WritetoDataFile
⑤、RemaptoPrivateView
下面详细介绍每个步骤的过程:
流程图:文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

 文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

journal文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

1、preplogbuffer:
Private view(PV) 中的数据并不是直接刷新到journal文件,而是通过一个中间内存块(journalbuffer,或者alogned buffer)一部分一部分的刷新到journal,这样可以提高并发。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

preplogbuffer即是将PV中的数据写入到aligned buffer中的过程。这个过程有两部分,basic write 操作和非 basic write操作(e.g.create file)。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

一次preplogbuffer是以一个commitJob为一个单位,可能会有很多个commitJob写入到aligned buffer,然后提交。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

一个commitJob中包含多个basic write 和非basic write 操作,basic write是存在Writeintent结构体中的,Writeintent记录了写操作的地址信息。非basic write 操作存在一个vector中。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

具体结构如下。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

journal文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

Aligned buffer 有自己的结构,这也是写入到journalfile中的结构。包含Jheader,JsectHeader lsn,Durop,JSectFooter:文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

journal文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

每个JsectHeader之间的Durop是属于一个事务范围,一起提交,一起成功,一起失败,即all-or-nothing.上篇文章中介绍的lsn文件,就是记录这个lsn号。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

2、WritetoJournal:
writetoJournal操作是将alignedbuffer刷新到JournalFile的过程。默认100ms刷新一次,由--journalCommitInterval 参数控制。writetoJournal会做一些checksum验证,将alignedbuffer进行压缩,然后将压缩过后的alignedbuffer写入到磁盘。写入磁盘后将删除已经满的Journal文件,更新lsn号到lsn文件。写操作到这一步就是安全的了,因为数据已经在磁盘上,如果使用getlasterror(j=true),这一步即可返回。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

3、WritetoDataFile:
WritetoDataFile是将未压缩的aligned buffer写入到shared view的过程,然后由操作系统刷新到磁盘文件中。WritetoDataFile首先会对aligned buffer进行严格的验证,确保没有改变过,然后解析aligned buffer,通过memcpy函数拷贝到shareview文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

4、RemaptoprivateView:
RemaptoprivateView会将持久化的数据重新映射到PV,以减小PV的大小,防止它不断扩大,按照源码上说,RemaptoprivateView会两秒钟重新映射一次,大约有1000个view,不是一次全做完,而是一部分一部分的做。由于读操作是读取PV,所以在映射完成之后会有短暂的时间读取磁盘。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

经过这四步,一个写操作就完成了,journal提高了数据的安全性,并不像想象中的会丢数据,重要的是如何使用和维护。
以上均参考自mongo官方文档和源码,有理解不对的地方也请大家指正。文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

参考:
1、journalFormat https://docs.google.com/drawings/edit?id=1iXjXZGz_ru6n-ub3EWMPtXBS424rH623nsyMQx8x4mo&hl=en
2、Dur process steps https://docs.google.com/drawings/edit?id=1TklsmZzm7ohIZkwgeK6rMvsdaR13KjtJYMsfLr175Zc&hl=en
3、http://www.mongodb.org/display/DOCS/Durability+Internals
转自:http://blog.chinaunix.net/uid-15795819-id-3419051.html文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/ 文章源自运维生存时间-https://www.ttlsa.com/mongodb/mongodb-durability-5/

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
默北
  • 本文由 发表于 27/06/2014 08:31:21
  • 转载请务必保留本文链接:https://www.ttlsa.com/mongodb/mongodb-durability-5/