使用MongoDB 3的Wired Tiger将会带来愉悦的事情

MongoDB 3的一个重大改变是数据持久化存储部分的实现。以前只能选择基于操作系统的MMAP存储引擎,现在还可以选择WiredTiger存储引擎。

总结一下使用WiredTiger的好处。

文档已被锁定

在MongoDB的2系列中,锁的单位是数据库,并且在MongoDB的3系列中,即使是传统的基于MMAP的存储引擎,也只能实现集合级别的锁定。但是,如果选择使用WiredTiger存储引擎,就可以实现文档级别的锁定。

通过这个方法,写入时的锁等待时间减少了。

现在可以将索引和数据存储在不同的目录中。

–通过wiredTigerDirectoryForIndexes选项,可以将索引与数据分开放置在不同的位置上。将内存放置于高速SSD中,而数据则可以进行精细的调整,例如放置在磁盘上。

现在可以限制内存使用量。

在传统的MMAP基础上,内存是由操作系统提供的,MongoDB无法控制。
因此,内存只能使用操作系统提供的,几乎没有限制地使用内存。
而WiredTiger则可以通过–wiredTigerCacheSizeGB选项来限制内存的使用量。

现在可以输出存储统计信息

使用wiredTigerStatisticsLogDelaySecs选项,可以定期地在数据目录下输出如下所示的存储运行统计信息。

Mar 19 00:57:21 77824 data/ block-manager: bytes read
Mar 19 00:57:21 155648 data/ block-manager: bytes written
Mar 19 00:57:21 0 data/ block-manager: mapped blocks read
Mar 19 00:57:21 5 data/ block-manager: blocks pre-loaded
Mar 19 00:57:21 18 data/ block-manager: blocks read
Mar 19 00:57:21 34 data/ block-manager: blocks written
Mar 19 00:57:21 14347 data/ cache: tracked dirty bytes in the cache
Mar 19 00:57:21 22224 data/ cache: bytes currently in the cache

我們現在可以進行資料壓縮。

在使用wiredTigerCollectionBlockCompressor选项时,可以对数据进行压缩。并且这种压缩可以针对每个集合进行控制。

可以进行索引压缩

通过设置”WiredTigerIndexPrefixCompression”选项,现在可以压缩索引的前缀。

数据文件的碎片化问题已经解决

根据MMAP(内存映射文件)方式,当删除文档或者文档变大并导致移动时,数据文件会产生空洞(即发生碎片化),导致数据文件比实际数据容量更大的问题。而且,由于这样的方式直接占用内存,还会增加内存使用量的压力。
而WiredTiger在插入数据时会对数据进行压缩,因此似乎不会出现这个问题。我在这篇博客中看到的。

做日记的方式发生了改变。

在MMAP基础上启用日志记录时,流程是先写入日志,然后再写入存储器。
而在WiredTiger中,引入了检查点机制,先将数据写入预写式日志,然后在检查点时将数据反映到存储器中。

MMAP基于WiredTiger,它们的日志记录功能完全不同,并且提供不同的保证。

在基于MMAP的系统中,由于更新文档的方式是直接更新现有数据,所以当MongoDB在写入文档的过程中崩溃时,由于没有进行日志记录,可能会导致下次启动时文档损坏,无法启动(需要运行”repair”命令来修复)。

在WiredTiger中,通过将旧数据保留并追加新版本的数据来更新文档,无论是否启用日志,文档的更新都是原子操作。换句话说,即使在日志无效且MongoDB在写入文档过程中崩溃,文档也不会损坏。

我們來解釋一下WiredTiger的日誌為何存在。在MongoDB中,數據被持久化到磁盤的單位叫做checkpoint(每60秒或2G寫入)。如果MongoDB崩潰且沒有啟用日誌,最後一次checkpoint之後的更新將丟失,無法持久化。但如果啟用了日誌,最近的更新將被持久化。

最后

由于传统的MMAP和WiredTiger可以在同一个复制集内共存,所以可以将主节点保持为MMAP,然后尝试将次节点使用WiredTiger进行运行,以观察情况。

请参考以下链接:
* http://docs.mongodb.org/manual/reference/program/mongod/
* http://docs.mongodb.org/manual/core/storage/

关于WiredTiger的实现(2016/4/15更新)

我稍微调查了一下关于WiredTiger的实现,现在补充一下。

MVCC(多版本并发控制)和CAS(比较并交换)

在MVCC(多版本并发控制)中,当更新数据时,并不是物理上覆盖旧数据,而是追加更新版本的数据。这样,在数据写入时,读取线程仍能够从旧版本中读取数据,从而提高吞吐量。

CAS(比较并交换)是用于数据更新的互斥控制。CAS允许线程在更新数据时发出指令,例如“前值是A,但现在要更新为B”。如果其他线程没有更新数据,则更新成功;如果其他线程已经更新了数据,则更新失败。这样就可以在不加锁的情况下更新数据。

以前的基于MMAP的方式是一种非常粗略的方式,直接更新数据库文件,导致数据库以单个数据库为单位进行加锁。然而,通过采用MVCC和CAS等方式,现在使用了WiredTiger,使得在多核环境下可以通过多个线程同时处理,并且提高了吞吐量。

参考以下内容:
* http://www.slideboom.com/presentations/133166
* http://www.slideshare.net/wiredtiger

广告
将在 10 秒后关闭
bannerAds