存储引擎(Storage Engine)是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上。从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引擎(Storage Engine),MongoDB支持的存储引擎有:WiredTiger,MMAPv1和In-Memory。算法
从MongoDB 3.2 版本开始,WiredTiger成为MongDB默认的Storage Engine,用于将数据持久化存储到硬盘文件中,WiredTiger提供文档级别(Document-Level)的并发控制,检查点(CheckPoint),数据压缩和本地数据加密( Native Encryption)等功能。mongodb
MongoDB不只能将数据持久化存储到硬盘文件中,并且还能将数据只保存到内存中;In-Memory存储引擎用于将数据只存储在内存中,只将少许的元数据和诊断日志(Diagnostic)存储到硬盘文件中,因为不须要Disk的IO操做,就能获取索取的数据,In-Memory存储引擎大幅度下降了数据查询的延迟(Latency)。数据库
一,指定MongoDB实例的存储引擎缓存
mongod 参数: --storageEngine wiredTiger | inMemory安全
指定Storage Engine的类型,并发
二,WiredTiger 存储引擎将数据存储到硬盘文件(Disk Files)app
WiredTiger和MMAPv1都用于持久化存储数据,相对而言,WiredTiger比MMAPv1更新,功能更强大。less
1,文档级别的并发控制(Document-Level Concurrency Control)ui
MongoDB在执行写操做时,WiredTiger 在文档级别进行并发控制,就是说,在同一时间,多个写操做可以修改同一个集合中的不一样文档;当多个写操做修改同一个文档时,必须以序列化方式执行;这意味着,若是该文档正在被修改,其余写操做必须等待,直到在该文档上的写操做完成以后,其余写操做相互竞争,获胜的写操做在该文档上执行修改操做。this
对于大多数读写操做,WiredTiger使用乐观并发控制(optimistic concurrency control),只在Global,database和Collection级别上使用意向锁(Intent Lock),若是WiredTiger检测到两个操做发生冲突时,致使MongoDB将其中一个操做从新执行,这个过程是系统自动完成的。
For most read and write operations, WiredTiger uses optimistic concurrency control. WiredTiger uses only intent locks at the global, database and collection levels. When the storage engine detects conflicts between two operations, one will incur a write conflict causing MongoDB to transparently retry that operation.
2,检查点(Checkpoint)
在Checkpoint操做开始时,WiredTiger提供指定时间点(point-in-time)的数据库快照(Snapshot),该Snapshot呈现的是内存中数据的一致性视图。当向Disk写入数据时,WiredTiger将Snapshot中的全部数据以一致性方式写入到数据文件(Disk Files)中。一旦Checkpoint建立成功,WiredTiger保证数据文件和内存数据是一致性的,所以,Checkpoint担当的是还原点(Recovery Point),Checkpoint操做可以缩短MongoDB从Journal日志文件还原数据的时间。
当WiredTiger建立Checkpoint时,MongoDB将数据刷新到数据文件(Disk Files)中,在默认状况下,WiredTiger建立Checkpoint的时间间隔是60s,或产生2GB的Journal文件。在WiredTiger建立新的Checkpoint期间,上一个Checkpoint仍然是有效的,这意味着,即便MongoDB在建立新的Checkpoint期间遭遇到错误而异常终止运行,只要重启,MongoDB就能从上一个有效的Checkpoint开始还原数据。
当MongoDB以原子方式更新WiredTiger的元数据表,使其引用新的Checkpoint时,代表新的Checkpoint建立成功,MongoDB将老的Checkpoint占用的Disk空间释放。使用WiredTiger 存储引擎,若是没有记录数据更新的日志,MongoDB只能还原到上一个Checkpoint;若是要还原在上一个Checkpoint以后执行的修改操做,必须使用Jounal日志文件。
3,预先记录日志(Write-ahead Transaction Log)
WiredTiger使用预写日志的机制,在数据更新时,先将数据更新写入到日志文件,而后在建立Checkpoint操做开始时,将日志文件中记录的操做,刷新到数据文件,就是说,经过预写日志和Checkpoint,将数据更新持久化到数据文件中,实现数据的一致性。WiredTiger 日志文件会持久化记录从上一次Checkpoint操做以后发生的全部数据更新,在MongoDB系统崩溃时,经过日志文件可以还原从上次Checkpoint操做以后发生的数据更新。
The WiredTiger journal persists all data modifications between checkpoints. If MongoDB exits between checkpoints, it uses the journal to replay all data modified since the last checkpoint.
3,内存使用
3.1 WiredTiger 利用系统内存资源缓存两部分数据:
从MongoDB 3.2 版本开始,WiredTiger内部缓存的使用量,默认值是:1GB 或 60% of RAM - 1GB,取两值中的较大值;文件系统缓存的使用量不固定,MongoDB自动使用系统空闲的内存,这些内存不被WiredTiger缓存和其余进程使用,数据在文件系统缓存中是压缩存储的。
3.2 调整WiredTiger内部缓存的大小
使用 mongod的参数 --wiredTigerCacheSizeGB 来修改MongoDB实例中WiredTiger内部缓存的大小,计算内部缓存大小的公式是:
4,数据压缩(Data Compression)
WiredTiger压缩存储集合(Collection)和索引(Index),压缩减小Disk空间消耗,可是消耗额外的CPU执行数据压缩和解压缩的操做。
默认状况下,WiredTiger使用块压缩(Block Compression)算法来压缩Collections,使用前缀压缩(Prefix Compression)算法来压缩Indexes,Journal日志文件也是压缩存储的。对于大多数工做负载(Workload),默认的压缩设置可以均衡(Balance)数据存储的效率和处理数据的需求,即压缩和解压的处理速度是很是高的。
5,Disk空间回收
当从MongoDB中删除文档(Documents)或集合(Collections)后,MongoDB不会将Disk空间释放给OS,MongoDB在数据文件(Data Files)中维护Empty Records的列表。当从新插入数据后,MongoDB从Empty Records列表中分配存储空间给新的Document,所以,不须要从新开辟空间。为了更新有效的重用Disk空间,必须从新整理数据碎片。
WiredTiger使用compact 命令,移除集合(Collection)中数据和索引的碎片,并将unused的空间释放,调用语法:
db.runCommand ( { compact: '<collection>' } )
在执行compact命令时,MongoDB会对当前的database加锁,阻塞其余操做。在compact命令执行完成以后,mongod会重建集合的全部索引。
On WiredTiger, compact will rewrite the collection and indexes to minimize disk space by releasing unused disk space to the operating system. This is useful if you have removed a large amount of data from the collection, and do not plan to replace it.
二,In-Memory 存储引擎将数据存储到内存(Memory)
In-Memory存储引擎将数据存储在内存中,除了少许的元数据和诊断(Diagnostic)日志,In-Memory存储引擎不会维护任何存储在硬盘上的数据(On-Disk Data),避免Disk的IO操做,减小数据查询的延迟。
1,指定In-Memory存储引擎
mongod --storageEngine inMemory --dbpath <path>
在选择In-Memory存储引擎时,须要指定两个参数:
2,文档级别的并发(document-level concurrency)
In-Memory存储引擎在执行写操做时,使用文件级别的并发控制,就是说,在同一时间,多个写操做可以同时修改同一个集合中的不一样文档;当多个写操做修改同一个文档时,必须以序列化方式执行;这意味着,若是该文档正在被修改,其余写操做必须等待。
3,内存使用
In-Mmeory 存储引擎须要将Data,Index,Oplog等存储到内存中,经过mongod参数: --inMemorySizeGB 设置占用的内存数量,默认值是:50% of RAM-1GB。指定In-Memory 存储引擎使用的内存数据量,单位是GB:
mongod --storageEngine inMemory --dbpath <path> --inMemorySizeGB <newSize>
4,持久化(Durable)
因为In-Memory 存储引擎不会持久化存储数据,只将数据存储在内存中,读写操做直接在内存中完成,不会将数据写入到Disk文件中,所以,不须要单独的日志文件,不存在记录日志和等待数据持久化的问题,当MongoDB实例关机或系统异常终止时,全部存储在内存中的数据都将会丢失。
5,记录oplog
In-Memory 存储引擎不会将数据更新写入到Disk,可是会记录oplog,该oplog是存储在内存中的集合,MongoDB经过Replication将Primary成员的oplog推送给同一副本集的其余成员。若是一个MongoDB实例是Replica Set的Primary成员,该实例使用In-Memory存储引擎,经过Replication将oplog推送到其余成员,在其余成员中重作oplog中记录的操做,这样,就能将在Primary成员中执行的数据修改持久化存储。
You can deploy mongod instances that use in-memory storage engine as part of a replica set. For example, as part of a three-member replica set, you could have:
With this deployment model, only the mongod instances running with the in-memory storange engine can become the primary. Clients connect only to the in-memory storage engine mongod instances. Even if both mongod instances running in-memory storage engine crash and restart, they can sync from the member running WiredTiger. The hidden mongod instance running with WiredTiger persists the data to disk, including the user data, indexes, and replication configuration information.
三,记录日志
数据是MongoDB的核心,MongoDB必须保证数据的安全,不能丢失,Journal 是顺序写入的日志文件,用于记录上一个Checkpoint以后发生的数据更新,可以将数据库从系统异常终止事件中还原到一个有效的状态。MongoDB使用预写日志机制实现数据的持久化:WiredTiger 存储引擎在执行写操做时,先将数据更新写入到Journal文件。Journal Files是存储在硬盘的日志文件,每一个Journal File大约是100MB,存储在--dbpath下的Journal子目录中,在执行Checkpoint操做,将数据的更新同步到数据文件。
每隔必定的时间间隔,WiredTiger 存储引擎都会执行Checkpoint操做,将缓存的数据更新日志同步到硬盘上的数据文件中(On-Disk Files),在默认状况下,MongoDB启用日志记录,也能够显式启用,只须要在启动mongod 时使用--journal 参数:
mongod --journal
1,使用Journal日志文件还原的过程
WiredTiger建立Checkpoint,可以将MongoDB数据库还原到上一个CheckPoint建立时的一致性状态,若是MongoDB在上一个Checkpoint以后异常终止,必须使用Journal日志文件,重作从上一个Checkpoint以后发生的数据更新操做,将数据还原到Journal记录的一致性状态,使用Journal日志还原的过程是:
MongoDB配置WiredTiger使用内存缓冲区来存储Journal Records,全部没有达到128KB的Journal Records都会被缓存在缓冲区中,直到大小超过128KB。在执行写操做时,WiredTiger将Journal Records存储在缓冲区中,若是MongoDB异常关机,存储在内存中的Journal Records将丢失,这意味着,WiredTiger将丢失最大128KB的数据更新。
WiredTiger syncs the buffered journal records to disk according to the following intervals or conditions:
New in version 3.2: Every 50 milliseconds.
MongoDB sets checkpoints to occur in WiredTiger on user data at an interval of 60 seconds or when 2 GB of journal data has been written, whichever occurs first.
If the write operation includes a write concern of j: true, WiredTiger forces a sync of the WiredTiger journal files.
Because MongoDB uses a journal file size limit of 100 MB, WiredTiger creates a new journal file approximately every 100 MB of data. When WiredTiger creates a new journal file, WiredTiger syncs the previous journal file.
3,日志文件(Journal Files)
关于Journal文件,MongoDB在 --dbpath 目录下建立 journal子目录,WiredTiger将Journal 文件存储在该目录下,每个Journal文件大约是100M,命名格式是:WiredTigerLog.<sequence>,sequence是一个左边填充0的10位数字,从0000000001开始,依次递增。
对于WiredTiger存储引擎,Journal 文件具备如下特性:
4,在异常宕机后恢复数据
在MongoDB实例异常宕机后,重启mongod实例,MongoDB自动重作(redo)全部的Journal Files,在还原Journal Files期间,MongoDB数据库是没法访问的。
四,mongod 跟存储引擎相关的参数
1,使用WiredTiger的参数设置
mongod --storageEngine wiredTiger --dbpath <path> --journal --wiredTigerCacheSizeGB <value> --wiredTigerJournalCompressor <compressor> --wiredTigerCollectionBlockCompressor <compressor> --wiredTigerIndexPrefixCompression <boolean>
2,使用In-Memory的参数设置
mongod --storageEngine inMemory --dbpath <path> --inMemorySizeGB <newSize> --replSet <setname> --oplogSize <value>
参考doc: