MongoDB如何使用wiredTiger?

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: Mongodb 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎,本文主要介绍Mongodb是如何使用wiredTiger数据库作为底层的数据存储层。目前还没有读过wiredTiger的源码,本文的内容都是基于wiredTiger官方文档,以及Mongodb.

Mongodb 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎,本文主要介绍Mongodb是如何使用wiredTiger数据库作为底层的数据存储层。目前还没有读过wiredTiger的源码,本文的内容都是基于wiredTiger官方文档,以及Mongodb对wiredTiger封装代码,有问题请指出。

wiredTiger引擎存储布局

wiredTiger(简称WT)支持行存储、列存储以及LSM等3种存储形式,Mongodb使用时,只是将其作为普通的KV存储引擎来使用,mongodb的每个集合对应一个WT的table,table里包含多个Key-value pairs,以B树形式存储。

以下是一个典型的使用WT存储引擎的数据目录布局(配置了directoryPerDB选项,启用了journal)

$tree
.
├── admin
│   ├── collection-11--5764503550749656746.wt
│   ├── collection-14--6907424972913303461.wt
│   ├── collection-16--6907424972913303461.wt
│   ├── collection-20--6907424972913303461.wt
│   ├── collection-8--6907424972913303461.wt
│   ├── collection-9--5764503550749656746.wt
│   ├── index-10--5764503550749656746.wt
│   ├── index-12--5764503550749656746.wt
│   ├── index-13--5764503550749656746.wt
│   ├── index-15--6907424972913303461.wt
│   ├── index-17--6907424972913303461.wt
│   └── index-9--6907424972913303461.wt
├── journal
│   ├── WiredTigerLog.0000000003
│   └── WiredTigerPreplog.0000000001
├── local
│   ├── collection-0--5764503550749656746.wt
│   ├── collection-2--5764503550749656746.wt
│   ├── collection-4--5764503550749656746.wt
│   ├── collection-6--5764503550749656746.wt
│   ├── collection-7--5764503550749656746.wt
│   ├── index-1--5764503550749656746.wt
│   ├── index-3--5764503550749656746.wt
│   ├── index-5--5764503550749656746.wt
│   └── index-8--5764503550749656746.wt
├── _mdb_catalog.wt
├── mongod.lock
├── products
│   ├── collection-6--6907424972913303461.wt
│   └── index-7--6907424972913303461.wt
├── sizeStorer.wt
├── storage.bson
├── WiredTiger
├── WiredTiger.basecfg
├── WiredTiger.lock
├── WiredTiger.turtle
└── WiredTiger.wt

WiredTiger*等文件存储WT的一些配置信息。

local、journal、admin、products等每个目录代表一个DB,DB里包含集合数据及集合的索引数据,每个集合的数据对应一个WT的table(一个.wt后缀的文件),集合的每项索引也对应一个WT的table。

journal目录下存储WT的write ahead log,当服务crash时,可通过log来恢复数据。

_mdb_catalog.wt里存储了所有集合的元数据,包括集合对应的WT table名字,集合的创建选项,集合的索引信息等,WT存储引擎初始化时,会从_mdb_catalog.wt里读取所有的集合信息,并加载元信息到内存。

集合名与WT table名的对应关系可以通过db.collection.stats()获取

mongo-9552:PRIMARY> db.system.users.stats().wiredTiger.uri
statistics:table:admin/collection-10--1436312956560417970

也可以直接dump出_mdb_catalog.wt里的内容查看,dump出的内容为BSON格式,阅读起来不是很方便。

wt -C "extensions=[/usr/local/lib/libwiredtiger_snappy.so]"  -h . dump table:_mdb_catalog

sizeStorer.wt里存储所有集合的容量信息,如文档数、文档总大小等,当插入、删除、更新文档时,这些信息会先cache到内存,没操作1000次会刷盘一次;mongod进程crash可能导致sizeStorer.wt里的数据与实际信息不匹配,可通过validate()命令来重新扫描集合以订正统计信息。

wiredTiger API

WT官方提供了C、java、python API,mongodb使用C API来访问WT数据库,主要包括3个核心的数据结构。

  1. WT_CONNECTION代表一个到WT数据库的连接,通常每个进程只用建立一个连接,WT_CONNECTION的所有方法都是线程安全的。
  2. WT_SESSION代表一个数据库操作的上下文,每个线程需创建独立的session。
  3. WT_CURSOR用于操作某个数据集(如某个table、file),可使用cursor来进行数据库插入、查询操作。

如下是使用wiredTiger C API的示例,展示了如何向WT数据库里插入数据,更多示例参考这里

#include <wiredtiger.h>

char *home = "WT_HOME";

int main(void)
{
    WT_CONNECTION *conn;
    WT_CURSOR *cursor;
    WT_SESSION *session;
    const char *key, *value;
    int ret;

    /* Open a connection to the database */
    ret = wiredtiger_open(home, NULL, "create", &conn);

    /* Open a session in conn */
    ret = conn->open_session(conn, NULL, NULL, &session);

    /* Create table if not exist */
    ret = session->create(session,
        "table:access", "key_format=S,value_format=S");

    /* Open a cursor and insert key-value pair */
   ret = session->open_cursor(session,
        "table:access", NULL, NULL, &cursor);
    cursor->set_key(cursor, "key1");
    cursor->set_value(cursor, "value1");
    ret = cursor->insert(cursor);

    /* Close conn */
    ret = conn->close(conn, NULL);

   return ret;
}

上述示例包含如下步骤

  1. wiredtiger_open()建立连接
  2. conn->open_session建立session
  3. session->create()创建access表,并指定key、value格式
  4. session->open_cursor创建cursor,并插入key-value
  5. 访问结束后conn->close()关闭连接

wiredTiger in Mongodb

Mongodb使用wiredTiger作为存储引擎时,直接使用其C API来存储、查询数据。

wiredtiger_open

Mongodb在WiredTigerKVEngine构造的时候wiredtiger_open建立连接,在其析构时关闭连接,其指定的配置参数为:

配置项 含义说明
create 如果数据库不存在则先创建
cache_size=xx cache大小,使用Mongod cacheSizeGB配置项的值
session_max=20000 最大session数量
eviction=(threads_max=4) 淘汰线程最大数量,用于将page从cache逐出
statistics=(fast) 统计数据采用fast模式
statistics_log=(wait=xx) 统计数据采集周期,使用mongod statisticsLogDelaySecs配置项的值
file_manager=(close_idle_time=100000) 空闲文件描述符回收时间
checkpoint=(wait=xx,log_size:2G) 开启周期性checkpoint,采用Mongod syncPeriodSecs配置项的值
log=(enabled=true,archive=true... 启用write ahead log,达到2G时触发checkpoint

重点介绍下checkpoint和log2个配置项,其决定了数据持久化的安全级别;wiredTiger支持2种数据持久化级别,分别是Checkpoint durability 和 Commit-level durability

Checkpoint durability

wiredTiger支持对当前的数据集进行checkpoint,checkpoint代表当前数据集的一个快照(或镜像),wiredTiger可配置周期性的进行checkpoint(或当log size达到一定阈值是做checkpoint)。

比如WT配置了周期性checkpoint(没开启log),每5分钟做一次checkpoint,在T1时刻做了一次Checkpoint得到数据集C1,则在接下来的5分钟内,如果服务crash,则WT只能将数据恢复到T1时刻。

Commit-level durability

wiredTiger通过write ahead log来支持commit-level durability。

开启write ahead log后,对WT数据库的更新都会先写log,log的刷盘策略(通过trasaction_sync配置项 或者 begion_transaction参数指定)决定了持久化的级别。

mongodb的使用的持久化级别配置为

  1. checkpoint=(wait=60,log_size=2G)
  2. log=(enabled=true,archive=true,path=journal,compressor=snappy)
  3. begin_transcation("sync=true")

具体策略为

  1. 每60s做一次checkpoint
  2. 开启write ahead log,当log size达到2GB时做checkpoint;并自动删除不需要的log文件。
  3. 每次commit_transaction时,调用fsync持久化已经commit的log。

基于上述配置,mongodb可以保证服务crash时,所有已经commit的操作都能通过log恢复。

open_session

mongodb使用session pool来管理WT的session,isolation=snapshot指定隔离级别为snapshot。

 conn->open_session(conn, NULL, "isolation=snapshot", &_session);

create table

创建数据集合的参数如下

配置项 含义说明
create 如果集合不存在则先创建
memory_page_max=10m page内存最大值
split_pct=90 page split百分比
checksum=on 开启校验
key_format=q,value_format=u key为int64_t类型(RecordId),value为WT_ITEM

数据集合的key为int64_t类型的RecordId,RerordId在集合内部唯一,value为二进制的BSON格式。

创建索引集合的参数如下

配置项 含义说明
create 如果集合不存在则先创建
type=file,internal_page_max=16k,leaf_page_max=16k 配置树节点大小
checksum=on 开启校验
key_format=u,value_format=u key-value均为WT_ITEM格式

索引集合的key、value均为二进制数据。

table创建好之后,就可以往table

比如,往某个集合插入一组元素

db.coll.insert({_id: "apple", count: 100});
db.coll.insert({_id: "peach", count: 200});
db.coll.insert({_id: "grape", count: 300});

对应一个coll的数据集合,其对应的WT数据类似于

key value
1 {_id: "apple", count: 100}
2 {_id: "peach", count: 200}
3 {_id; "grape", count: 300}

以及基于id的索引集合,其对应的WT数据类似于

key value
"apple" 1
"peach" 2
"grape" 3

接下来如果在count上建索引,索引会存储在新的WT table里,数据类似于

db.coll.ensureIndex({count: -1})
key value
300 3
200 2
100 1

总结

Mongodb使用wiredTiger存储引擎时,其将wiredTiger作为一个KV数据库来使用,mongodb的集合和索引都对应一个wiredTiger的table。并依赖于wiredTiger提供的checkpoint + write ahead log机制提供高数据可靠性。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
5月前
|
存储 NoSQL 算法
MongoDB存储引擎发展及WiredTiger深入解析(二)
MongoDB存储引擎发展及WiredTiger深入解析(二)
|
12月前
|
存储 NoSQL Shell
如何将阿里云WiredTiger引擎的MongoDB物理备份文件恢复至自建数据库
数据库操作一直是一个比较敏感的话题,动不动“删库跑路”,可见数据库操作对于一个项目而言是非常重要的,我们有时候会因为一个游戏的严重bug或者运营故障要回档数据库,而你们刚好使用的是阿里云的Mongodb,那么这篇文章将给你提供一个思路(或许你按照阿里云官网的文档一顿操作下来,并不是那么顺利,有一些报错,无法登录...)
|
存储 NoSQL
MongoDB 存储引擎 WiredTiger 原理解析
在团队内部分享了 Wiredtiger 引擎的原理,为此画了多张图来辅助说明,对了解 Wiredtiger 应该是非常有帮助的,内容分享出来给大家。暂时没时间整理文字版,对实现原理非常感兴趣的同学,如果PPT没讲明白,可以找我私下交流。
MongoDB 3.2.9 请求 hang 分析及 wiredtiger 调优
MongoDB 3.2.9 版本在 wiredtiger 上做了很多改进,但不幸的时,这个版本引入了一个新的 bug,持续大量 insert/update 场景,有一定的可能导致 wiredtiger 进入 deadlock,MongoDB 官方迅速的在3.2.10里修复了该问题,该版本在 wir.
|
存储 NoSQL 关系型数据库
MongoDB WiredTiger 存储引擎cache_pool设计 (上) -- 原理篇
## 1. MongoDB 多引擎体系 -- WiredTiger MongoDB v.3.0之前的版本,默认使用`MMAP(MMap引擎)`方式对内存中的数据进行写盘存储,遭受了很多诟病。比如`并发受限的表锁、不支持压缩、不可控的IO`操作等,MMAP甚至不能称作一个完整的存储引擎(笔者的个人观点),对数据(Btree的数据页、索引页)的操作甚至要依赖os的mmap(in_page_ca
7022 0
|
存储 NoSQL 数据库
MongoDB Wiredtiger存储引擎实现原理
Mongodb Wiredtiger存储引擎实现原理 Mongodb-3.2已经WiredTiger设置为了默认的存储引擎,最近通过阅读wiredtiger源代码(在不了解其内部实现的情况下,读代码难度相当大,代码量太大,强烈建议官方多出些介绍文章),理清了wiredtiger的大致原理,并简单总