MongoDB Wiredtiger存储引擎实现原理

Mongodb Wiredtiger存储引擎实现原理

Mongodb-3.2已经WiredTiger设置为了默认的存储引擎,最近通过阅读wiredtiger源代码(在不了解其内部实现的情况下,读代码难度相当大,代码量太大,强烈建议官方多出些介绍文章),理清了wiredtiger的大致原理,并简单总结,不保证内容都是正确的,如有问题请指出,欢迎讨论交流。

按照Mongodb默认的配置,WiredTiger的写操作会先写入Cache,并持久化到WAL(Write ahead log),每60s或log文件达到2GB时会做一次Checkpoint,将当前的数据持久化,产生一个新的快照。

Wiredtiger的Cache采用Btree的方式组织,每个Btree节点为一个page,root page是btree的根节点,internal page是btree的中间索引节点,leaf page是真正存储数据的叶子节点;btree的数据以page为单位按需从磁盘加载或写入磁盘。

Wiredtiger采用Copy on write的方式管理修改操作(insert、update、delete),修改操作会先缓存在cache里,以skiplist的形式组织;持久化时,修改操作不会在原来的leaf page上进行,而是写入新分配的page,每次checkpoint都会产生一个新的root page。

Checkpoint时,wiredtiger需要将btree修改过的PAGE都进行持久化存储,每个btree对应磁盘上一个物理文件,btree的每个PAGE以文件里的extent形式(由文件offset + size标识)存储,一个Checkpoit包含如下元数据:

  • root page地址,地址由文件offset,size及内容的checksum组成
  1. alloc extent list地址,存储从上次checkpoint起新分配的extent列表
  2. discard extent list地址,存储从上次checkpoint起丢弃的extent列表
  3. available extent list地址,存储可分配的extent列表,只有最新的checkpoint包含该列表
  4. file size 如需恢复到该checkpoint的状态,将文件truncate到file size即可

Mongodb里一个典型的Wiredtiger数据库存储布局大致如下

$tree
.
├── journal
│   ├── WiredTigerLog.0000000003
│   └── WiredTigerPreplog.0000000001
├── WiredTiger
├── WiredTiger.basecfg
├── WiredTiger.lock
├── WiredTiger.turtle
├── admin
│   ├── table1.wt
│   └── table2.wt
├── local
│   ├── table1.wt
│   └── table2.wt        
└── WiredTiger.wt
  • WiredTiger.basecfg存储基本配置信息
  • WiredTiger.lock用于防止多个进程连接同一个Wiredtiger数据库
  • table*.wt存储各个tale(数据库中的表)的数据
  • WiredTiger.wt是特殊的table,用于存储所有其他table的元数据信息
  • WiredTiger.turtle存储WiredTiger.wt的元数据信息
  • journal存储Write ahead log

一次Checkpoint的大致流程如下

  1. 对所有的table进行一次Checkpoint,每个table的Checkpoint的元数据更新至WiredTiger.wt
  2. 对WiredTiger.wt进行Checkpoint,将该table Checkpoint的元数据更新至临时文件WiredTiger.turtle.set
  3. 将WiredTiger.turtle.set重命名为WiredTiger.turtle

上述过程如中间失败,Wiredtiger在下次连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性。

参考资料

  1. Wiredtiger官方文档
  2. Wiredtiger internal
  3. Wiredtiger Block Manager Overview

你可能感兴趣的:(MongoDB Wiredtiger存储引擎实现原理)