MongoDB mmapv1存储引擎解析

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: mongodb的mongod服务管理一个数据目录,可包含多个DB,每个DB的数据单独组织,本文主要介绍mmapv1存储引擎的数据组织方式。 Database 每个Database(DB)由一个.ns文件及若干个数据文件组成 $ll mydb.* -rw------- 1 ydzhang

mongodb的mongod服务管理一个数据目录,可包含多个DB,每个DB的数据单独组织,本文主要介绍mmapv1存储引擎的数据组织方式。

Database

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

$ll mydb.*
-rw-------  1 ydzhang  staff  67108864  7  4 14:05 mydb.0
-rw-------  1 ydzhang  staff  16777216  7  4 14:05 mydb.ns

数据文件从0开始编号,依次为mydb.0、mydb.1、mydb.2等,文件大小从64MB起,依次倍增,最大为2GB。

Namespace

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

hash表里的一个节点包含的元数据结构如下,每个节点大小为628Bytes,16M的NS文件最多可存储26715个namespace。

struct Node {
    int hash;
    Namespace key;
    NamespaceDetails value;
};

  • key为namespace的名字,为固定长度128字节的字符数组。
  • hash为namespce的hash值,用于快速查找
  • value包含一个namespace所有的元数据

namespace元数据结构如下:

class NamespaceDetails {
    DiskLoc firstExtent; // 第一个extent位置
    DiskLoc lastExtent;  // 最后一个extent位置
    DiskLoc deletedListSmall[SmallBuckets]; 
    // 不同大小的删除记录列表
    ...
};

其中DiskLoc代表某个数据文件的具体偏移位置,数据文件使用mmap映射到内存空间进行管理,内存的管理(哪些数据何时换入/换出)完全交给OS管理。

 class DiskLoc {
    int _a;  // 数据文件编号,如mydb.0编号为0
    int ofs; // 文件内部偏移
 };

数据文件

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

namesapce的元数据里包含指向第一个及最后一个extent的位置指针,通过这些信息,就可以遍历一个namespace下的所有extent数据。

每个数据文件包含一个固定长度头部DataFileHeader

 class DataFileHeader {
    DataFileVersion version;
    int fileLength;
    DiskLoc unused;
    int unusedLength;
    DiskLoc freeListStart;
    DiskLoc freeListEnd;
    char reserve[];
 };

Header中包含数据文件版本、文件大小、未使用空间位置及长度、空闲extent链表起始及结束位置。extent被回收时,就会放到数据文件对应的空闲extent链表里。

unusedLength为数据文件未被使用过的空间长度,unused则指向未使用空间的起始位置。

Extent

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

struct Extent {
    unsigned magic;  // 用于检查extent数据有效性
    DiskLoc myLoc;   // extent自身位置

    /* 前一个/后一个 extent位置指针 */
    DiskLoc xnext;
    DiskLoc xprev;

    int length;  // extent总长度 

    DiskLoc firstRecord;  // extent内第一个record位置指针
    DiskLoc lastRecord;   // extent内最后一个record位置指针
    char _extentData[4];  // extent数据
};

Record

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

class Record {
    int _lengthWithHeaders;  // Record长度
    int _extentOfs;          // Record所在的extent位置指针
    int _nextOfs;            // 前一个Record位置信息
    int _prevOfs;            // 后一个Record位置信息
    char _data[4];           // Record数据
};

Record被删除后,会以DeleteRecord的形式存储,其前两个字段与Record是一致的。

class DeletedRecord {
   int _lengthWithHeaders;  // record长度
   int _extentOfs;          // record所在的extent位置指针
   DiskLoc _nextDeleted;    // 下一个已删除记录的位置
};

一个namespace下的所有的已删除记录(可以回收并复用的存储空间)以单向链表的形式,为了最大化存储空间利用率,不同size(32B、64B、128B...)的记录被挂在不同的链表上,NamespaceDetail里的deletedListSmall/deletedListLarge包含指向这些不同大小链表头部的指针。

enter image description here

写入Record

  1. 检查对应的namespace对应的删除记录链表里是否有合适的DeletedRecord可以利用,如果有,则直接复用删除空间写入记录。
  2. 检查数据文件的freeList里是否有合适大小的空闲extent可以利用,如果有则直接利用空闲的extent,将记录写入。
  3. 第1、2步都不成功,则写创建新的extent写入记录;创建新extent时,如果当前的数据文件没有足够的空闲空间,则创建新的数据文件。

删除Record

删除的记录会以DeleteRecord的形式插入到对应集合的删除链表里,删除的空间在下一次写入新的记录时可能会被利用上;但也有可能一直用不上而浪费。比如某个128Bytes大小的记录被删除后,接下来写入的记录一直大于128B,则这个128B的DeletedRecord不能有效的被利用。

当删除很多时,可能产生很多不能重复利用的"存储碎片",从而导致存储空间大量浪费;可通过对集合进行compact来整理存储碎片。

更新Record

更新Record时,分2种情况

  1. 更新的Record比原来小,可以直接复用现有的空间(原地更新);多余的空间如果足够多,会将剩余空间插入到DeletedRecord链表;
  2. 更新的Record比原来大,更新相当于删除 + 新写入,原来的空间会插入到DeletedRecord链表里。

更新跟删除类似,也有可能产生很多存储碎片;如果业务场景里更新很多,可通过合理设置Record Padding,尽量让每次更新都直接复用现有存储空间。

查询Record

没有索引的情况下,查询某个Record需要遍历整个集合,读取出符合条件的Record;如果经常需要根据每个纬度查询Record,则需要给集合建立索引以提供查询效率。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
3月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB的MMAPv1存储引擎
在MongoDB 3.2版本之前,默认使用MMAPv1存储引擎。MMAPv1包括Database、Namespace、数据文件、Extent和Record等组件。每个Database由名称空间文件和数据文件组成,数据文件按编号递增,大小从64MB到2GB。每个数据文件被划分为多个Extent,每个Extent包含多个Record,对应MongoDB中的文档。通过一个示例展示了如何配置和使用MMAPv1存储引擎。
|
3月前
|
存储 NoSQL MongoDB
MongoDB面试专题33道解析
大家好,我是 V 哥。今天为大家整理了 MongoDB 面试题,涵盖 NoSQL 数据库基础、MongoDB 的核心概念、集群与分片、备份恢复、性能优化等内容。这些题目和解答不仅适合面试准备,也是日常工作中深入理解 MongoDB 的宝贵资料。希望对大家有所帮助!
|
4月前
|
存储 NoSQL MongoDB
MongoDB 概念解析
10月更文挑战第12天
57 0
MongoDB 概念解析
|
3月前
|
存储 缓存 NoSQL
【赵渝强老师】MongoDB的WiredTiger存储引擎
MongoDB WiredTiger存储引擎自3.2版本起成为默认选择,提供文档级别的并发控制、检查点、数据压缩和本地加密等功能。本文详细介绍了WiredTiger的并发控制机制、预写日志与检查点、内存使用、数据压缩及磁盘空间回收等特性。
147 0
|
3月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB的In-Memory存储引擎
MongoDB的In-Memory存储引擎将数据存储在内存中,显著减少查询延迟,提高性能。该引擎不会将数据持久化到硬盘,仅在内存中存储,因此重启后数据会丢失。本文通过创建目录、配置文件、启动服务、插入数据和查询等步骤,详细演示了如何使用In-Memory存储引擎。
|
3月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB的存储引擎
存储引擎是MongoDB的核心组件,负责管理数据在硬盘和内存中的存储方式。从3.2版本起,MongoDB支持WiredTiger、MMAPv1和In-Memory三种存储引擎。WiredTiger为默认引擎,提供文档级并发控制和数据压缩;MMAPv1在3.2版本前为默认引擎,4.x版本后不再支持;In-Memory引擎将数据存储在内存中,减少查询延迟。
|
6月前
|
C# 开发者 Windows
全面指南:WPF无障碍设计从入门到精通——让每一个用户都能无障碍地享受你的应用,从自动化属性到焦点导航的最佳实践
【8月更文挑战第31天】为了确保Windows Presentation Foundation (WPF) 应用程序对所有用户都具备无障碍性,开发者需关注无障碍设计原则。这不仅是法律要求,更是社会责任,旨在让技术更人性化,惠及包括视障、听障及行动受限等用户群体。
121 0
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
122 2
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

相关产品

  • 云数据库 MongoDB 版
  • 推荐镜像

    更多