MongoDB逻辑架构及存储引擎介绍

     学习一门新的语言,几乎所有的指引都是从helloWorld开始,学习数据库也一样,我们一般从查询语句学起,但之后我们要思考数据是如何存储的,查询怎样才能更高效,本文从MongoDB的逻辑架构、存储引擎和索引来进行分析,以便我们更深的了解MongoDB。

     下图是MongoDB的逻辑架构,来源于参照官方文档:

           MongoDB逻辑架构及存储引擎介绍

    


    存储引擎作为数据库的组件,决定了数据如何存储,

     MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,目前除了早期的MMAP存储引擎外,还有WiredTiger和In-Memory Storage Engine等,前者更是在被MongoDB公司收购后更是直接引入到了MongoDB 3.0版本中,在3.2版本中的默认存储引擎是WiredTiger

下边分别对两种存储引擎进行介绍,

WriedTiger逻辑架构

 MongoDB逻辑架构及存储引擎介绍

WiredTiger.basecfg存储基本配置信息

WiredTiger.lock用于防止多个进程连接同一个Wiredtiger数据库

 table*.wt存储各个tale(数据库中的表)的数据

WiredTiger.wt是特殊的table,用于存储所有其他table的元数据信息

WiredTiger.turtle存储WiredTiger.wt的元数据信息

 journal存储Write ahead log

 按照Mongodb默认的配置,WiredTiger的写操作会先写入Cache,并持久化到WAL(Write ahead log),每60slog文件达到2GB时会做一次Checkpoint,将当前的数据持久化,产生一个新的快照。Wiredtiger连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性。

MongoDB逻辑架构及存储引擎介绍

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

Wiredtiger采用Copy onwrite的方式管理修改操作(insertupdatedelete),修改操作会先缓存在cache里,持久化时,修改操作不会在原来的leaf page上进行,而是写入新分配的page,每次checkpoint都会产生一个新的root page

MongoDB逻辑架构及存储引擎介绍

WriedTiger特性

DocumentLevel Concurrency(文档级别的锁):多个写操作可以同时修改同一集合中的不同文档,修改同一文档时必须串行执行。

Snapshotsand Checkpoints(快照和检查点):mongoDB每60秒或日志文件【jonurnal】达到2G会创建一个检查点(产生一个snapshot[快照]),该Snapshot呈现的是内存中数据的一致性视图,当向Disk写入数据时,WiredTiger将Snapshot中的所有数据以一致性方式写入到数据文件(Disk Files)中

Journal(日志): 开启 journal 后,每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据),一次写入,会对应数据、索引,oplog的修改,而这3个修改,会对应一条journal操作日志

Compression(压缩):WiredTiger压缩存储集合(Collection)和索引(Index),压缩减少Disk空间消耗,但是消耗额外的CPU执行数据压缩和解压缩的操作。

默认情况下,WiredTiger使用块压缩(Block Compression)算法来压缩Collections,使用前缀压缩(Prefix Compression)算法来压缩Indexes,Journal日志文件也是压缩存储的。对于大多数工作负载(Workload),默认的压缩设置能够均衡(Balance)数据存储的效率和处理数据的需求,即压缩和解压的处理速度是非常高的。

 MemoryUse(内存使用)

从MongoDB 3.2 版本开始,WiredTiger内部缓存的使用量,默认值是:1GB 或 60% of RAM - 1GB,取两值中的较大值;文件系统缓存的使用量不固定,MongoDB自动使用系统空闲的内存,这些内存不被WiredTiger缓存和其他进程使用,数据在文件系统缓存中是压缩存储的。

MMAPV1存储引擎逻辑架构:

个Database(DB)由一个.ns文件及若干个数据文件组成 

存储按照db来分目录, 每个db目录下有 .ns文件 {dbname}.0, {dbname}.1 等文件。

 MongoDB逻辑架构及存储引擎介绍

 

 

Namespace

每个DB包含多个namespace(对应mongodb的collection名),mydb.ns实际上是一个hash表(采用线性探测方式解决冲突),用于快速定位某个namespace的起始位置。

数据文件

每个数据文件被划分成多个extent,每个extent只包含一个namespace的数据,同一个namespace的所有extent之间以双向链表形式组织。

Extent

每个extent包含多个Record(对应mongodb的document),同一个extent下的所有record以双向链表形式组织。

Record

每个Record对应mongodb里的一个文档,每个Record包含固定长度16bytes的描述信息。

mmap引擎加载某个database时,首先初始化namespaceIndex,namespaceIndex相当于database的元数据入口。因此.ns文件是一个hashtable的内存镜像。

 

MMAPV1存储引擎特性:

Journal(日志) :为了确保所有更改都能持久化到数据文件中,mongoDB通过写文件文件的方式来保证,同时也可以通过日志文件来恢复数据。

RecordStorage Characteristics(记录存储特性):顺序存储、记录分配的空间不够,会重新分配,耗时并产生碎片,3.0以后版本采用2倍倍增方式,(如:32,64,128…2MB),如果记录超过2M,将分配最接近2MB的倍数(如果大小是3MB,那可能就是分配4MB)。

RecordAllocation Strategies(记录分配策略):mongoDB允许在给一条记录分配空间的时候留一点空闲空间,以便更新操作,这样来减少空间再分配。当然对一些固定的行也可以在建立文档的时候指定不需要些特性。

MemoryUse(内存使用):使用MMAPv,mongodb 自动使用所有机器的空闲的内存作为它的cache,系统资源监视器监视mongodb 使用的内存情况,这意外这着mongodb将尽可能多的使用空闲的内存,如果其他的进程突然需要服务器大量的内存,mongdb将会释放内存给其它进程。  

 MongoDB索引

MongoDB中的索引和其他数据库索引类似,也是使用B-Tree结构。MongoDB的索引是在collection级别上的,并且支持在任何列或者集合内的文档的子列中创建索引。

mongoDB支持_id索引 、单键索引、多键索引(当一个被索引的值是数组时,MongoDB会索引这个数组中的每一个元素。更多信息在 multikey模块有详细说明)、复合索引(多个字段,可以分别指定升降序)、时期过期索引(过一段时间索引失效)、全文索引、地理位置索引、稀疏索引(允许索引的字段为空值,建立时跳过)、部分索引(对满足条件的字段建立索引,比如给月工资1W以上的小伙伴建立索引)