前言
上一篇介绍了Mongodb历史和适合场景,这一篇将要学习MongoDB原理
一、MongoDB 原理
????????MongoDB 存取读写速度快,甚至可以用来当作缓存数据库。但是在使用过程中会发现 MongoDB 服务非常占内存,几乎是服务器有多少内存就会占用多少内存。为什么会出现这种情况呢?我们要 从 MongoDB 的读写工作流程和对内存的使用方式说起 。
????????MongoDB 在存取工作流程上有一个非常酷的设计决策,MongoDB 的所有数据实际上是存放在 硬盘的,然后把部分或者全部要操作的数据通过内存映射存储引擎映射到内存中。 即是:虚拟内存 +持久化的存储方式。
?????????如果是读操作,直接从内存中取数据,如果是写操作,就会修改内存中对应的数据,然后就不 需要管了。操作系统的虚拟内存管理器会定时把数据刷新保存到硬盘中。 内存中的数据什么时候写 到硬盘中,则是操作系统的事情了。
MongoDB 的存取工作流程区别于一般硬盘数据库在于两点:
????????读:一般硬盘数据库在需要数据时才去硬盘中读取请求数据, MongoDB 则是尽可能地放入内 存中。
????????写:一般硬盘数据库在有数据需要修改时会马上写入刷新到硬盘,MongoDB 只是修改内存中的 数据就不管了,写入的数据会排队等待操作系统的定时刷新保存到硬盘。
MongoDB 的设计思路有两个好处:
(1) 将什么时候调用 IO 操作写入硬盘这样的内存管理工作交给操作系统的虚拟内存管理 器来完成,大大简化了 MongoDB 的工作。
(2) 把随机的写操作转换成顺序的写操作,顺其自然地写入,而不是有数据修改就调 IO 操 作去写入,这样减少了 IO 操作,避免了零碎的硬盘操作,大幅度提升性能。
但是这样的设计思路也有坏处:
(1) 如果 MongoDB 在内存中修改了数据,在数据刷新到硬盘之前,停电了或者系统岩机 了,就会丢失数据了。
针对这样的问题, MongoDB 设计了 Journal 模式, Journal 是服务器意外岩机的情况下,将数 据库操作进行重演的日志。如果打开 Journal ,默认情况下 MongoDB 100 毫秒(这是在数据文件 和 Journal 文件处于同磁盘卷上的情况,而如果数据文件和 Journal 文件不在同磁盘卷上时,默认 刷新输出时间是 30 毫秒)往 Journal 文件中 flush 次数据,那么即使断电也只会丢失 100ms 的数 据,这对大多数应用来说都可以容忍了。从版 1.9.2+, MongoDB 默认打开 Journal 功能,以确保数 据安全。而且 Journal 的刷新时间是可以改变的,使用--journalCommitInterval 命令修改,范围是 2~300ms 值越低,刷新输出频率越高,数据安全度也就越高,但磁盘性能上的开销也更高。MongoDB 存取工作流程的实现关键在于通过内存映射存储引擎把数据映射到内存中。
二、存储原理
MongoDB 目前支持的 MMAP,MMAPV1,WiredTiger 以及 In-Memory 存储引擎。我们主要讲 WiredTiger 引擎。
MMAPV1(3.2 之前默认)(B 树)
? 采用 Linux 操作系统内存映射技术,所以不支持压缩
? 会尽可能多的使用内存,默认会使用所有的空闲内存,但当别的进程需要使用的时候会释放部 分内存
? 采用集合级锁,导致并发吞吐量较低
? 善于处理大量插入,更新,删除的操作
WiredTiger(3.2 以上版本默认)(B+树)
? 采用文档型锁,吞吐量相对高许多
? 相比 MMAPV1 存储索引时 WiredTiger 使用前缀压缩,更节省对内存空间的损耗
? 提供压缩算法,可以大大降低对硬盘资源的消耗,节省约 60%以上的硬盘资源;
? 支持 snappy(默认)和 zlib 两种压缩模式
? 默认每分钟一次 checkpoint,及数据持久化
三、WiredTiger 引擎
官方讲解:https://docs.mongoing.com/cun-chu/cun-chu-yin-qing/wiredtiger-storage-engine《WiredTiger存储引擎》
详情强烈参考:https://mp.weixin.qq.com/s/Wuzh47jsBh5QonBrZxUnjg 《WiredTiger 存储引擎系列》
四、内存使用
通过 WiredTiger,MongoDB 可以利用 WiredTiger 内部缓存和文件系统缓存。
从 MongoDB 3.4 开始,默认的 WiredTiger 内部缓存大小是以下两者中的较大者: 50%(RAM-1 GB)或 256 MB。
例如,在总共有 4GB RAM 的系统上,WiredTiger 缓存将使用 1.5GB RAM? 0.5 *(4 - 1)= 1.5 GB)。 相反,总内存为 1.25 GB 的系统将为 WiredTiger 缓存分配 256 MB,因为这是总 RAM 的一半以上减去一 GB 0.5 *(1.25? -? 1)= 128 MB
mongodb写入流程
1、wiredTiger 写操作先到 cache,并持久化 WAL
2、每 60s 或 log 文件达到 2G,则执行一次 Checkpoint 持久化,产生一个新快照。
3、wiredTiger 连接初始化时,先将数据恢复到最新的快照,再根据 WAL 恢复数据。
Cache
Cache 采用 Btree 方式组织,每个 Btree 节点为一个 page,数据以 page 为单位按需从磁盘加载或写入磁盘
root page:Btree 的根节点
internal page:中间索引节点
page:叶子节点,数据存储在此节点。
增删改
采用 Copy on write 的方式管理 insert、update、delete。
修改操作:
1、数据读入 Cache 里,
2、对数据修改,
3、持久化时,写入新的 page(不会写原来的 leaf page)。
4、执行 Chechpoint 之后,产生新的 page。
Checkpoint 每次 Checkpoint 的过程:
1、对所有的 table 进行一次 Checkpoint,将每个 table 的 Checkpoint 的元数据更新到 WiredTiger.wt。
2、再对 WiredTiger.wt 进行 Checkpoint,将 Checkpoint 的 meta 数据更新到 WiredTiger.turtle.set 3、将 WiredTiger.turtle.set 重命名为 WiredTiger.turtle。
WiredTiger 包含以下文件:
WiredTiger.basecfg :存储基本配置信息 WiredTiger.lock 用于防止多个进程连接同一个 WiredTiger 数据库
table*.wt 存储各个 table 的数据
WiredTiger.wt:是特殊的 table,用于存储所有其他 table 的 meta 数据信息
WiredTiger.turtle:存储 WireTiger.wt 的 meta 数据信息
四、Mongodb部署方式
单机使用:主要用于开发测试。
复制集集群
?
?官方统计百分之七八十的线上项目采用复制集的方式进行部署。
分片集群
10%左右采用分片集群的方式部署。
总结
? ? ? 学习了MongoDB的工作原理。
?技术参考
C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂
|