MongoDB(引擎)


关于存储引擎 WiredTiger storage engine

WiredTiger 在3.2版本成为mongodb的默认存储引擎。所以这里讲的就是WiredTiger了。

Document Level Concurrency

WiredTiger提供了document-level concurrency control 的写操作,这么说,多个client可以在同一时间内修改同一collection的不同文档。对于大多数读写操作,WiredTiger都会使用最佳的并发控制,在global、database、collection等级别上只使用了意向锁(intent lock)。如果存储引擎检测到两个操作冲突了,则导致mongodb将其中一个操作重新执行。

Snapshots and Checkpoints

MongoDB配置WiredTiger在每60秒或者2GB日志数据就创建一个checkpoint(快照)。在写入一个checkpoint时,前一个checkpoint仍然是有效的,所以在此时MongoDB如果崩溃了,还是可以回退到最新的有效checkpoint,并依靠日志来恢复最近的改变。在新的checkpoint成功变成有效的,之前的旧checkpoint pages就会被释放。

Journal

MongoDB在没有新的checkpoint生成之前,会持续地打日志,使用的是snappy compression library来压缩日志,但是也可以指定其他的压缩算法,这可通过storage.wiredTiger.engineConfig.journalConpressor来设置。甚至设置storage.journal.enabled=false来关闭日志系统,这样可以减少花费,但是所做的修改也就很危险。

MongoDB配置了WiredTiger在内存指定缓冲区中进行记录,等到达 128 kb 时再写到磁盘中去。将内存中的记录写入磁盘有下面一些条件:

  • 每经过100ms。
  • 新的checkpoint出现,或者日志数据到达2GB。
  • 如果设置了write concern 的j:true选项,存储引擎立刻写入log file。

最小的log记录是128字节,如果等于小于128字节则不使用压缩。log file的大小规定为100M,所以存储引擎大约每100M的日志数据就创建一个log file,一般会预先创建一些log file(通常是在首次启动mongod实例之前,此功能可以关闭)。除非写操作特别多,否则一般情况下只会有两三日志文件。正常关闭mongod时会清空所有的日志文件,而非正常关闭则会留下一些文件。

如果在日志信息仍在内存缓冲区的时候mongd突然崩溃(如断电),这些日志数据就会丢失。最有可能丢失的就是崩溃前的100ms再加上写进日志文件的这一时间段。serverStatus
命令中有log的统计信息。

如果频繁写日志文件会导致效率的下降,这时可以将journal目录转移到其他文件系统中,就不会影响到数据库正常的读写操作效率。但这会带来的一个问题是,对数据库使用snapshot时不能够对这两个部分单独进行操作,而是需要使用fsyncLock()将数据库锁起来,等snapshot操作都完成之后再使用fsyncUnlock()解锁。

Compression

MongoDB提供collection压缩和index压缩。默认是使用block compression来压缩collection,和使用prefix compression来压缩index。
对于collection,可以更改指定压缩算法或者禁用压缩,使用storage.wiredTiger.collectionConfig.blockCompressor设置即可。
对于index,可以使用storage.wiredTiger.indexConfig.prefixCompression来关闭prefix压缩。
甚至,针对每个collection和index的压缩,可以使用具体的压缩算法,参考create-collection-storage-engine-optionsdb.collection.createIndex()。不过,默认的压缩算法在大多数平均情况下都有出色的表现,很好平衡了效率和执行需求。

Cache

MongoDB使用了双Cache,一个是WiredTiger Cache,一个是文件系统Cache。默认情况下,从3.2起WiredTiger将使用60%的RAM减去1GB或者使用1GB,取其中的大者。在3.0中要么使用1GB,要么50%的物理内存,取其中的大者。可以参考storage.wiredTiger.engineConfig.cacheSizeGB
--wiredTigerCacheSizeGB进行配置Cache大小,但是要避免超过默认的大小,值得注意的是,storage.wiredTiger.engineConfig.cacheSizeGB仅仅限制了WiredTiger Cache的大小,这只是mongod的一部分,而不是mongod所使用内存的上限。MongoDB假设了这只有一个instance在一个node上而已,如果有多个的话,更加需要调整一下Cache大小。

本引擎会自主决定哪些数据保存在内存中,哪些数据会刷新到磁盘中。而且,两种引擎不能混淆使用,即用Wired Tiger创建的数据库不能用MMAPv1去打开,这是两种不同的文件存储方式以及管理方式的。


关于MMAPv1 storage engine

每个文档中的所有field都位于同一块连续的内存中,而storage engine在为文档申请内存块的时候都是会留出一部分内存供后来填充用的,即为每个文档申请的实际内存大小都会大于其真实大小(一般是以2的指数增长)。当填充的多余部分内存用光了之后,就会引起重新为该文档申请新内存的操作。

Document Level Lock

本引擎也提供了锁的机制,对于document级别的写操作保证了不会冲突,而是进行有序的执行。


MongoDB 系统的限制与门槛

  • BSON文档
    最大BSON文档的大小是16MB,如果超过这个限制,可以尝试使用GridFS API来存储大文件。
  • 嵌套深度
    MongoDB目前支持的内嵌文档的嵌套深度是不超过100层。
  • Namespace 长度
    支持的最大的集合namespace为120 Bytes,其中包括了数据库名称,还有dot等等,即<database>.<collection>
  • Namespace 的数量
    在3.0之前使用的默认存储引擎就会有一些限制,比如Namespace的数量受限制于namespace文件的大小,现在的默认存储引擎WiredTiget就没有这些限制了。
  • Namespace 文件的大小
    之前MMAPv1默认的namespace文件的大小限制为16MB,但是可以通过nsSize来配置它,只要不超过2047字节。但WiredTiger现在没有这个限制。
  • 固定集合Capped Collection。如果是通过max参数来创建的固定集合,那么集合大小不能超过232。而在创建固定集合的时候没有指定集合大小,那么集合中可以包含任意多个文档。
  • MMAPv1存储引擎限制了每个数据库不能够超过16000个数据文件,即不超过32TB,可通过storage.mmapv1.smallFiles来设置为8TB。
  • MMAPv1不能够处理数据大小超过操作系统的虚存空间大小。而WiredTiger没有此限制。
  • MMAPv1限制了数据库中的文档数量,与索引数量和namespace文件大小相关。WiredTiger没有此限制。
  • 针对具体情况,可以使用no padding模式的申请内存方式,这样每次申请的内存大小就刚刚好了。

GridFS 大文档存储

如果存储的文档超过了16MB,那么就需要选择这种方式来存储了。将大文档分割成小部分或chunk,然后分别作为小文档存储起来,分别存储于两个集合collection中,其中一个集合存储的是文件chunk,另一个存储的是元数据(这里有详细介绍 GridFS Collections)。默认的chunk大小为255kB,即除了最后一块,其他都是255kB(自从v 2.4.10改为255kB的)。
在需要查询大文件的时候,引擎会重组所有的chunk。可以针对文件中的某个范围进行查询,比如跳过视频的片头。这种存储方式也支持16MB以下的文档存储的,当经常需要查询文件中的某个范围的时候就能派上用场了。

一般情况下,GridFS使用两个分别名为fs.filesfs.chunks的文件来保存所有的大文件信息。一对文件称之为“桶”,可以创建多对,也可以选择其他名称。chunks中的每个文档都是一个chunk,就像下面这样:

{ 
  "_id" : <ObjectId>, 
  "files_id" : <ObjectId>,
  "n" : <num>,   //sequence of this chunk
  "data" : <binary>
}

files中的每个文档代表着GridFS中的一个大文件。除了部分是可选的,文档格式大致如下:

{ 
  "_id" : <ObjectId>, 
  "length" : <num>, 
  "chunkSize" : <num>, 
  "uploadDate" : <timestamp>, 
  "md5" : <hash>, 
  "filename" : <string>, 
  "contentType" : <string>, 
  "aliases" : <string array>, 
  "metadata" : <dataObject>
}

那效率如何呢?GridFS对每个chunks和files集合使用了index,驱动一般会自动创建这些索引,提升速度就只能依靠这些索引了,也可以自定义一些新索引。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容