存储引擎

最近更新时间:2019-07-05 15:46:21

云数据库 MongoDB 支持 MongoRocks 和 WiredTiger 两种引擎。

MongoRocks 引擎

MongoRocks 引擎基于 RocksDB 打造,RocksDB 作为一种 KV 存储,非常适合 MongoDB 文档结构。
目前 MongoRocks 引擎支持 MongoDB 3.2(稳定版本)、MongoDB 3.4(稳定版本)及 MongoDB 3.6(非稳定版本,不支持3.6版本的 Change Stream 等特性)。

MongoRocks 优缺点

由于 MongoRocks 基于 RocksDB 打造,因此 MongoRocks 具备了 LSM(Log Structured Merge)存储系统常见的优缺点,包括:

  • 读放大
    RocksDB 的读,会首先读 MemTable,如果 MemTable 没有找到的话,需要从新到旧(从上到下)一层一层查找 SST 文件,直到找到想要的数据,这个过程可能需要不止一次 I/O。虽通过布隆过滤器和 Cache 会对读放大有改善,但是在范围查询等场景下,读放大还是比较明显。
  • 写放大
    每次写入操作对 RocksDB 来说需要经过 Immutable MemTable 持久化为 SST level0,level0 合并 level1 如此下去,一次写请求会产生多次磁盘 I/O。SSD 的使用寿命和其写入量有关,因此在 SSD 的硬件上写放大需要重点关注。
  • 磁盘放大
    所有的写操作都是追加写,因此过期的数据不会马上被清理掉。
  • 写入限制
    WriteStall 引起的卡顿在 RocksDB 中,如果写入速度超过了 MemTable 持久化的速度和 SST 合并的速度,引擎会限制用户写入的速度。否则,SST 文件会急剧增加,读的性能也会因为 SST 文件的增加而降低。因此在写入速度过快后可能会有卡顿的现象。

腾讯云对 MongoRocks 的优化

背景

在原生的 MongoRocks 中,当 oplog 空间达到 capped collection 大小上限时,会触发 delete oplog 动作,经过写放大后,将产生较多的磁盘 I/O。oplog 特点如下:

  • 严格按照时间有序递增,因此存储到 RocksDB 中也是按照 key 排序好的。
  • 只有 insert,没有 update,因此在 sstfile 中是无需进行 compaction 的。
  • 删除时只会从最早的时间删除,即从最早的 sstfile 开始删除。

优化

针对 oplog 的特点,我们将 oplog 和 oplog 的元信息单独放在两个 ColumnFamily 中,利用 compact 来对 oplog 进行清理,仅会产生极少的 I/O。具体流程为:

  • 判断是否需要删除多余的 oplog(采用了空间超额2个 sst file 大小的条件)。
  • 获取 oplog 的 sstfile 元信息,从最早的 sstfile 开始遍历,直到 sstfile 的总大小超过了需要删除的空间。
  • 调用 compaction filter 的最大删除时间,设置为上面找到的 sstfile 集群的最大 key。
  • 主动调用 compactRange,删除 oplog 经过这样的优化,清理 oplog 仅会产生极少的 I/O。

MongoRocks 适用场景

目前 MongoRocks 在业内已广泛使用,腾讯内部,诸如缓存冷数据、微信账单冷数据等均使用 MongoRocks 引擎。

  • 时延毛刺要求极高的场景
    实践发现 WiredTiger 引擎的 cache 大于索引大小时性能表现出色,但索引不完全在内存时数据库会触发 eviction,此时请求的延迟会大幅增大,而 MongoRocks 性能平稳很多。
  • 多表场景
    在 WiredTiger 引擎中,每个表和索引被单独存储为一个文件,当表个数过多时硬盘上会产生大量小文件,严重影响性能。从实践经验来看,当集合个数达到数千个以后数据库的性能将变差。而 MongoRocks 引擎不会为每个表创建一个文件,可以避免该问题。
  • 冷数据存储场景
    冷数据的场景下,为成本考虑,通常会将冷数据存放在 SATA 等廉价存储介质上,WiredTiger 引擎在机械硬盘上性能表现也不如意,特别是 eviction 情况下,而 MongoRocks 引擎会将 I/O 的随机写转换为顺序写,这对机械硬盘非常友好。

WiredTiger 引擎

WiredTiger 是一种典型的 Btree 结构。

引擎对比

测试环境:
CPU:Inter Xeon 2.3GHz、24核
内存:50GB Cache
硬盘:PCIE-SSD
版本:MongoDB 3.2 版本 WiredTiger 及 MongoRocks 引擎

测试性能 测试结果
磁盘空间消耗 测试模型:单条文档500B,写入500GB后,对比硬盘数据文件大小。
测试结论:同样的数据 MongoRocks 引擎对磁盘空间的消耗略高于 WiredTiger 引擎。
100%读性能对比 测试模型:单集合500GB数据,随机读取数据,预热数据10分钟后,记录之后10分钟内的 QPS。
测试结论:读性能 MongoRocks 略高于 WiredTiger 引擎,在纯读的场景下,QPS 比较稳定。
100%写性能对比 测试模型:单条文档500B,写入500GB后,对比之后10分钟内的写入速度。
测试结论:写性能 MongoRocks 明显优于 WiredTiger 引擎,而且在写入过程中 MongoRocks 未出现 WiredTiger 的性能跌落现象。
读写比例1:1性能对比 测试模型:单条文档500B,写入500GB后,以1:1比例进行读写操作,预热数据10分钟后,记录之后10分钟内的 QPS。
测试结论:读写1:1混合的场景下,MongoRocks 和 WiredTiger 引擎性能基本持平,但 WiredTiger 引擎会存在一些性能的毛刺。