目录
引言
MongoDB 是目前主流的 NoSQL 数据库之一,与关系型数据库和其它的 NoSQL 不同,MongoDB 使用了面向文档的数据存储方式,将数据以类似 JSON 的方式存储在磁盘上。WiredTiger是MondoDB v3.0之后的默认存储引擎,面向多核、Page IO优化做了很多工作,支持行存储与列存储,支持B-Tree和LSM两种结构组织数据。MongoDB在使用WiredTiger作为存储引擎时,默认配置是使用了B-Tree结构。本文将基于源码对WiredTiger引擎进行简要分析,描述WiredTiger的数据page组织方式。由于MongoDB主要使用行存储,并且对于普通的kv存储而言,通常使用行存储完成,因此本文主要分析行存储的场景。
背景
整体架构
WiredTiger对外部通过cursor方式来实现数据的search/insert/update/remove操作,内部通过journal_log、checkpoint、cache(btree/cache_evict)、block_manager子模块协调访问IO存储(这里主要列出本文相关模块,sweep、transaction、bloom/lsm等未列出)。
- Session 模块:负责和wt引擎上层交互的句柄,每个session会关联多个cursor,cursor属于一个session
- cache 模块:主要有内存中的btree page(数据页,索引页,溢出页)构成
- evict 模块:如果cache内存紧张,触发cache淘汰,遍历btree,并根据lru排序淘汰
- Journal 模块:WAL log,类似InnoDB的redolog,保证数据持久化,通过定时和定量阈值来flush
- checkpoint 模块:类似InnoDB checkpoint机制,异步执行btree刷盘,checkpoint之后通知log模块更新log_ckpt_lsn(lsn概念和InnoDB一致)
- block manager模块:负责磁盘IO的读写,cache、evict、checkpoint模块均通过该模块访问磁盘
数据组织结构
在介绍WiredTiger的数据组织前,先来看看传统数据库引擎的数据组织方式,一般存储引擎都是采用btree或者lsm tree来实现索引,但是索引的最小单位不是K/V记录对象,而是数据页,数据页的组织关系实现就是存储引擎的数据组织方式。传统数据库引擎大都是设计一个磁盘和内存完全一样的数据组织方式,这个结构是固定的空间大小。而WT没有像传统的数据库引擎那样设计一套内存和磁盘page完全一致的数据组织方式,而是针对磁盘和CPU、内存三者之间特点设计了一套独特的数据组织方式,这种数据组织结构分为两部分:
- In-memory page: 内存中的数据页(page)
- On-disk extent:基于磁盘文件的偏移量的范围存储
WT内存中的page是一个松散自由的数据结构,而磁盘上的extent只是一个变长的经过了序列化的数据块,这样做的目的(设计目标)有以下几点:
- 内存中的page松散结构可以不受磁盘存储方式的限制,可以自由的构建page的无锁多核并发结构,充分发挥CPU多核的能力。
- 可以自由的在内存page和磁盘extent之间实现数据的压缩,提高磁盘的存储效率和减少I/O访问时间
数据页
通过上面的介绍已经对WiredTiger的数据组织基本的了解,WT数据组织方式就是in-memory page加on-disk extent。我们首先从简单的磁盘部分来做分析。