WiredTiger 在3.2版本成为mongodb的默认存储引擎。因此这里讲的就是WiredTiger了。node
Document Level Concurrency算法
WiredTiger提供了document-level concurrency control 的写操做,这么说,多个client能够在同一时间内修改同一collection的不一样文档。对于大多数读写操做,WiredTiger都会使用最佳的并发控制,在global、database、collection等级别上只使用了意向锁(intent lock)。若是存储引擎检测到两个操做冲突了,则致使mongodb将其中一个操做从新执行。mongodb
Snapshots and Checkpoints数据库
MongoDB配置WiredTiger在每60秒或者2GB日志数据就建立一个checkpoint(快照)。在写入一个checkpoint时,前一个checkpoint仍然是有效的,因此在此时MongoDB若是崩溃了,仍是能够回退到最新的有效checkpoint,并依靠日志来恢复最近的改变。在新的checkpoint成功变成有效的,以前的旧checkpoint pages就会被释放。并发
Journalapp
MongoDB在没有新的checkpoint生成以前,会持续地打日志,使用的是snappy compression library来压缩日志,可是也能够指定其余的压缩算法,这可经过storage.wiredTiger.engineConfig.journalConpressor
来设置。甚至设置storage.journal.enabled=false
来关闭日志系统,这样能够减小花费,可是所作的修改也就很危险。this
MongoDB配置了WiredTiger在内存指定缓冲区中进行记录,等到达 128 kb 时再写到磁盘中去。将内存中的记录写入磁盘有下面一些条件:spa
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-options
和db.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去打开,这是两种不一样的文件存储方式以及管理方式的。
每一个文档中的全部field都位于同一块连续的内存中,而storage engine在为文档申请内存块的时候都是会留出一部份内存供后来填充用的,即为每一个文档申请的实际内存大小都会大于其真实大小(通常是以2的指数增加)。当填充的多余部份内存用光了以后,就会引发从新为该文档申请新内存的操做。
Document Level Lock
本引擎也提供了锁的机制,对于document级别的写操做保证了不会冲突,而是进行有序的执行。
<database>.<collection>
。storage.mmapv1.smallFiles
来设置为8TB。GridFS 大文档存储
若是存储的文档超过了16MB,那么就须要选择这种方式来存储了。将大文档分割成小部分或chunk,而后分别做为小文档存储起来,分别存储于两个集合collection中,其中一个集合存储的是文件chunk,另外一个存储的是元数据(这里有详细介绍 GridFS Collections)。默认的chunk大小为255kB,即除了最后一块,其余都是255kB(自从v 2.4.10改成255kB的)。
在须要查询大文件的时候,引擎会重组全部的chunk。能够针对文件中的某个范围进行查询,好比跳过视频的片头。这种存储方式也支持16MB如下的文档存储的,当常常须要查询文件中的某个范围的时候就能派上用场了。
通常状况下,GridFS使用两个分别名为fs.files
和fs.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,驱动通常会自动建立这些索引,提高速度就只能依靠这些索引了,也能够自定义一些新索引。