MongoDB如何使用wiredTiger?

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机制提供高数据可靠性。

时间: 2024-09-16 17:08:11

MongoDB如何使用wiredTiger?的相关文章

MongoDB 存储引擎 WiredTiger 原理解析

在团队内部分享了 Wiredtiger 引擎的原理,为此画了多张图来辅助说明,对了解 Wiredtiger 应该是非常有帮助的,内容分享出来给大家.暂时没时间整理文字版,对实现原理非常感兴趣的同学,如果PPT没讲明白,可以找我私下交流.

mongodb一些使用技巧或注意事项记录

1.有的时候需要删除指定字段那一列,使用update操作.例如要删除name这一列: query  json: {"name":{$exists:true}} update json: {$unset:{"name":""}} 2.数据导出,在mongodb的bin目录执行mongoexport命令并设定相关的参数,例如: ./mongoexport -h 192.168.0.201 --port 27017 –d admin –u admin

MongoDB使用教程系列文章--开篇

根据DB-Engines的排名统计,MongoDB综合排名第四(2016年1月数据,前三名分别是Oracle,MySQL,SQL Server),NoSQL领域(非RDBMS)里排名第一.尤其是在2015年里,一口气发布了两个大版本,3月发布了3.0版本,11月发布3.2版本. 在3.2版本中开始突破NoSQL的枷锁,提供了Join操作,可见其并不满足于NoSQL"独角兽"的称呼,目标早已定位成NewSQL,向RDBMS发起挑战. 但MongoDB毕竟不是RDBMS,甚至在数据建模上有

Performing Data Write Operations with MongoDB

Introduction This article discusses the steps involved in performing data write operations with MongoDB, focusing on the roles of the Journal and Oplog applications. Journal is a concept on the MongoDB storage engine layer while plog is a capped coll

一篇文章,掌握所有开源数据库的现状

  数据库作为业务的核心,在整个基础软件栈中是非常重要的一环.近几年社区也是新的方案和思想层出不穷,接下来我将总结一下近几年一些主流的开源数据库方案,其背后的设计思想以及适用场景.本人才疏学浅如有遗漏或者错误请见谅.本次分享聚焦于数据库既结构化数据存储 OLTP 及 NoSQL 领域,不会涉及 OLAP.对象存储.分布式文件系统. 1 开源RDBMS与互联网的崛起 很长时间以来,关系型数据库一直是大公司的专利,市场被 Oracle / DB2 等企业数据库牢牢把持.但是随着互联网的崛起.开源社区

KV存储的对比

最近对各种KV存储进行一个比较,从存储引擎到存储引擎的类型,到单机版的kvstore,再到分布式kvstore集群. 存储引擎的类型 类型 全称 btree LSH Log-Structured Hash Table LSM Log-Structured Merge Tree FractalTree 分型树 存储引擎 类型 名称 语言 备注 应用在___ dbengine排名 出品 berkeleyDB BTREE, HASH, QUEUE, RECNO C,Java No.9 oracle W

MongoDB WiredTiger 存储引擎cache_pool设计 (下) -- 实践篇

1. Cache Pool引发的问题 之前的文章<MongoDB WiredTiger 存储引擎cache_pool设计 (上) -- 原理篇>和大家分享WiredTiger的整体架构和Cache Pool相关的设计,这篇来介绍下阿里云MongoDB线上出现的问题,及改进措施. 用过MongoDB 3.0之后版本的同学应该都比较熟悉WiredTiger的cache evict问题. 连续好几个版本在cache 淘汰算法上设计都有些小问题,现象总结起来就是写入hang住.本文使用的是MongoD

MongoDB WiredTiger 存储引擎cache_pool设计 (上) -- 原理篇

1. MongoDB 多引擎体系 -- WiredTiger MongoDB v.3.0之前的版本,默认使用MMAP(MMap引擎)方式对内存中的数据进行写盘存储,遭受了很多诟病.比如并发受限的表锁.不支持压缩.不可控的IO操作等,MMAP甚至不能称作一个完整的存储引擎(笔者的个人观点),对数据(Btree的数据页.索引页)的操作甚至要依赖os的mmap(in_page_cache)刷盘,并且os的page 4k为IO单元对数据库本身就是不友好的,再加上其实数据库自身应该比OS更懂数据的layo

MongoDB Wiredtiger存储引擎实现原理

Mongodb Wiredtiger存储引擎实现原理 Mongodb-3.2已经WiredTiger设置为了默认的存储引擎,最近通过阅读wiredtiger源代码(在不了解其内部实现的情况下,读代码难度相当大,代码量太大,强烈建议官方多出些介绍文章),理清了wiredtiger的大致原理,并简单总结,不保证内容都是正确的,如有问题请指出,欢迎讨论交流. 按照Mongodb默认的配置,WiredTiger的写操作会先写入Cache,并持久化到WAL(Write ahead log),每60s或l