Mongodb如何使用wiredTiger?
2016-12-02 09:05
519 查看
MongoDB 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎,本文主要介绍Mongodb是如何使用wiredTiger数据库作为底层的数据存储层。目前还没有读过wiredTiger的源码,本文的内容都是基于wiredTiger官方文档,以及Mongodb对wiredTiger封装代码,有问题请指出。
wiredTiger(简称WT)支持行存储、列存储以及LSM等3种存储形式,Mongodb使用时,只是将其作为普通的KV存储引擎来使用,mongodb的每个集合对应一个WT的table,table里包含多个Key-value pairs,以B树形式存储。
以下是一个典型的使用WT存储引擎的数据目录布局(配置了directoryPerDB选项,启用了journal)
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()获取
也可以直接dump出_mdb_catalog.wt里的内容查看,dump出的内容为BSON格式,阅读起来不是很方便。
sizeStorer.wt里存储所有集合的容量信息,如文档数、文档总大小等,当插入、删除、更新文档时,这些信息会先cache到内存,没操作1000次会刷盘一次;mongod进程crash可能导致sizeStorer.wt里的数据与实际信息不匹配,可通过validate()命令来重新扫描集合以订正统计信息。
WT官方提供了C、Java、Python API,mongodb使用C
API来访问WT数据库,主要包括3个核心的数据结构。
WT_CONNECTION代表一个到WT数据库的连接,通常每个进程只用建立一个连接,WT_CONNECTION的所有方法都是线程安全的。
WT_SESSION代表一个数据库操作的上下文,每个线程需创建独立的session。
WT_CURSOR用于操作某个数据集(如某个table、file),可使用cursor来进行数据库插入、查询操作。
如下是使用wiredTiger C API的示例,展示了如何向WT数据库里插入数据,更多示例参考这里。
上述示例包含如下步骤
wiredtiger_open()建立连接
conn->open_session建立session
session->create()创建access表,并指定key、value格式
session->open_cursor创建cursor,并插入key-value
访问结束后conn->close()关闭连接
Mongodb使用wiredTiger作为存储引擎时,直接使用其C API来存储、查询数据。
Mongodb在WiredTigerKVEngine构造的时候wiredtiger_open建立连接,在其析构时关闭连接,其指定的配置参数为:
重点介绍下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的使用的持久化级别配置为
checkpoint=(wait=60,log_size=2G)
log=(enabled=true,archive=true,path=journal,compressor=snappy)
begin_transcation(“sync=true”)
具体策略为
每60s做一次checkpoint
开启write ahead log,当log size达到2GB时做checkpoint;并自动删除不需要的log文件。
每次commit_transaction时,调用fsync持久化已经commit的log。
基于上述配置,mongodb可以保证服务crash时,所有已经commit的操作都能通过log恢复。
mongodb使用session pool来管理WT的session,isolation=snapshot指定隔离级别为snapshot。
创建数据集合的参数如下
数据集合的key为int64_t类型的RecordId,RerordId在集合内部唯一,value为二进制的BSON格式。
创建索引集合的参数如下
索引集合的key、value均为二进制数据。
table创建好之后,就可以往table
比如,往某个集合插入一组元素
对应一个coll的数据集合,其对应的WT数据类似于
以及基于id的索引集合,其对应的WT数据类似于
接下来如果在count上建索引,索引会存储在新的WT table里,数据类似于
Mongodb使用wiredTiger存储引擎时,其将wiredTiger作为一个KV数据库来使用,mongodb的集合和索引都对应一个wiredTiger的table。并依赖于wiredTiger提供的checkpoint + write ahead log机制提供高数据可靠性。
张友东](http://yunnotes.NET),就职于阿里云飞天技术部,主要关注分布式存储、Nosql等技术领域,参与TFS(淘宝分布式文件系统)、KVStore(Redis云服务)等项目的开发工作,欢迎交流。
顶0
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使用CAPI来访问WT数据库,主要包括3个核心的数据结构。
WT_CONNECTION代表一个到WT数据库的连接,通常每个进程只用建立一个连接,WT_CONNECTION的所有方法都是线程安全的。
WT_SESSION代表一个数据库操作的上下文,每个线程需创建独立的session。
WT_CURSOR用于操作某个数据集(如某个table、file),可使用cursor来进行数据库插入、查询操作。
如下是使用wiredTiger C API的示例,展示了如何向WT数据库里插入数据,更多示例参考这里。
#include 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; }
上述示例包含如下步骤
wiredtiger_open()建立连接
conn->open_session建立session
session->create()创建access表,并指定key、value格式
session->open_cursor创建cursor,并插入key-value
访问结束后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 |
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的使用的持久化级别配置为
checkpoint=(wait=60,log_size=2G)
log=(enabled=true,archive=true,path=journal,compressor=snappy)
begin_transcation(“sync=true”)
具体策略为
每60s做一次checkpoint
开启write ahead log,当log size达到2GB时做checkpoint;并自动删除不需要的log文件。
每次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 |
创建索引集合的参数如下
配置项 | 含义说明 |
---|---|
create | 如果集合不存在则先创建 |
type=file,internal_page_max=16k,leaf_page_max=16k | 配置树节点大小 |
checksum=on | 开启校验 |
key_format=u,value_format=u | key-value均为WT_ITEM格式 |
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} |
KEY | VALUE |
---|---|
“apple” | 1 |
“peach” | 2 |
“grape” | 3 |
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机制提供高数据可靠性。
转载作者简介
张友东](http://yunnotes.NET),就职于阿里云飞天技术部,主要关注分布式存储、Nosql等技术领域,参与TFS(淘宝分布式文件系统)、KVStore(Redis云服务)等项目的开发工作,欢迎交流。顶0
相关文章推荐
- Mongodb如何使用wiredTiger?
- 如何避开MongoDB使用中的一些陷阱
- 如何在shell下使用JavaScript和Mongodb交互?
- MongoDB中如何不使用_id作为主键?曲线救国?
- MongoDB数据使用-如何在Windows环境下使用mongorestore命令导入bson文件
- centos 7 如何安装启动使用mongodb
- mmap-MongoDB如何使用内存
- mongoDB何时使用分片及如何分片
- Mongodb(1)——存储引擎WiredTiger的使用
- 如何使用MongoDB自带的json库来反序列json字符串
- 如何在thinkPHP5中使用mongoDB中空间搜索进行位置范围查找
- 如何使用MongoDB
- MongoDB监控项--如何使用命令得到
- ThinkJS中如何使用MongoDB的CURD操作
- 如何使用php文件测试mongodb是否安装成功
- golang中使用mongodb的操作类以及如何封装
- 如何使用容器实现生产级别的MongoDB sharding集群的一键交付
- mongoDB 性能优化:如何使用普通查询语句替代 aggregate 操作?
- 如何在.Net中使用MongoDB
- 如何安装mongodb服务以及如何使用可视化工具连接mongodb数据库