专栏首页二进制文集思维导图学《Mongo 官方文档》

思维导图学《Mongo 官方文档》

前言

本文是对 Mongo 官方文档粗略的总结,并没有涉及到很深的细节(细节还是直接看官方文档吧)。我认为 Mongo 有重要的就 3 点:

  1. 存储引擎原理,如何保证断电后恢复数据?Mongo 的 data 在文件系统中,是如何组织和保存的?
  2. Replication
  3. Sharding

思维导图

目录

目录

Basic

Aggregation & Data Modeling

Indexes

Storage

Replication & Sharding

思考

Document 在内部是如何存储的?

每个 Document 被保存在一个 Record 中。Record 相当于 MongoDB 内部分配的一块空间,除了保存 Document 的内容可能还会预留一些填充的额外空间。对于写入后的 Document 如果还会更新,可能导致 Document 长度增加,就可以利用上额外的填充空间来。若业务对于写入后的 Document 不会再更新或删除(像监控日志、流水记录等),可以指定无填充的 Record 分配策略,更节省空间。

单个 Document 的容量是否有限制?

16MB。Document 这种 JSON 形态天生会带来数据存储冗余,主要是 field 属性每个 Document 都会保存一遍。目前 3.2 版本的 MongoDB 已经将新的 WiredTiger 作为默认存储引擎,它提供了压缩功能,有两种压缩形式:

  • Snappy 默认压缩算法,在压缩率和 CPU 开销之间取得平衡。
  • Zlib 更高的压缩率,但也带来更高的 CPU 开销。

而每个 Document 依然有最大容量限制,不能无限增长下去,这个限制目前是 16MB。那么我要存大于 16MB 的文件怎么办,MongoDB 提供了 GridFS 来存储超过 16MB 大小的文件。如下图所示,一个大文件被拆分成小的 File Chunk,每个 Chunk 大小 255KB,并存放在一个 Document 中。GridFS 使用了 2 个 Collection 来分别存放文件 Chunk 和文件元数据。

遇到真正的「大数据」(单机存储容量不够)怎么办?

分片化:利用更多的机器来提供更大的容量,分片集群采用代理模式:

而每个分片上的数据又以 Chunk 的形式组织(类似于 Redis Cluster 的 Slot 概念),以便于集群内部的数据迁移和再平衡。比较容易混淆的是这里的 Chunk 不是前面 GridFS 里提到的 Chunk,它们的关系大概如下图:

Mongo 的数据安全吗?在保证效率的同时,在服务器突然宕机的情况下,是否能够保存数据?

安全效率其实是相互制约的,越安全则效率越低,越高效则越不安全。MongoDB 的设计场景考虑的是应对大量的数据写入和查询,而数据的重要性相对没那么高。所以 MongoDB 的默认设置在安全和效率之间,更偏向效率。

Write To Buffer Without ACK

这个模式下 MongoDB 是不确认写请求的,Client 端调用驱动写入后若没有网络错误就认为成功,实际到底写入成功没有是不确定的。即使网络没有问题,数据到达 MongoDB 后它先保存在内存 Buffer 中,再异步写入 Journaling 日志,这中间有 100ms(默认值) 的落盘(写入磁盘)时间窗口。一般数据库的设计都是先写 Journaling 的流水日志,随后异步再写真正的数据文件到磁盘,这个可能就比较长了,MongoDB 是 60 秒或者 Journaling 日志达到 2G。

Write To Buffer With ACK

这个比上一种模式稍微好一点,MongoDB 收到写入请求,先写入内存 Buffer 后回发 Ack 确认。Client 端能确保 MongoDB 收到了写入数据,但依然有短暂的 Journaling 日志落盘时差导致潜在的数据丢失可能。

Write To Journaling With ACK

这个模式确保至少写入 Journaling 日志后才回发 Ack 确认,Client 端能确保数据至少写入磁盘了,安全性较高。

Write To Replica Buffer With ACK

这个模式是针对多副本集的,为了提升数据安全性,除了及时写入磁盘也可以通过写多个副本来提升。在这个模式下,数据至少写入 2 个副本的内存 Buffer 中才回发 Ack 确认。虽然都在内存 Buffer 中,但两个实例在落盘短暂的 100ms 时差中同时故障的概率很低,所以安全性有所提升。

MMAPv1 和 WiredTiger 有什么区别?

  • MMAPv1 是 Mongo 在 3.0 以前的存储引擎,WiredTiger 是 Mongo 在 3.2 及以后版本的默认存储引擎;
  • MMAPv1 只是单纯地将 BSON 数据直接存储在磁盘上,WiredTiger 则会在数据从内存存储到磁盘前进行一次压缩
  • MMAPv1 在 3.0 版本之前,以 database 为单位加锁,对同一个Database的其他Collection所做的操作也会被阻塞。 而到了 3.0 版本,MMAPv1 则开始使用以 Collection 为单位的加锁。WiredTiger 是基于 Document 级锁机制。

MMAPv1 是如何分配记录的?

在MongoDB中,每条数据以 Document 的形式进行存储,并通过 Collection 来管理Document。同一个Collection中的Document会根据插入(insert)的先后顺序, 连续地写入到磁盘的同一个区域(region)上。MMAP在第一次插入时会为每个Document开辟一小块专属的区域,你可以管它叫一个"record"(记录),或一个"slot"(record这个名字容易和别的东西混淆,所以后面我会管它叫slot), 其他新插入的Document则必须从这一小块区域的结尾处开始写入。

为了避免 update 时 Document 变大重新分配空间,创建 Document 时会预留一定的空间,称为 padding,可以降低重新分配 Document 的几率。

WiredTiger 是如何实现 Document 级锁的?

在平常的使用中,大多数对数据库的更新操作都只会对某个 Collection 中的少量 Document 进行更新。对多个Collection进行同时更新的情况已是十分稀有,对多个 Database 进行同时更新则是更为罕见了。 由此可见,加锁粒度最小只支持到 Collection 是远远不够的。相对于 MMAPv1,WiredTiger 使用的实际为 Document 级的乐观锁机制。

WiredTiger的乐观锁机制与其他乐观锁机制实现大同小异。WiredTiger会在更新Document前记录住即将被更新的所有Document的当前版本号,并在进行更新前再次验证其当前版本号。 若当前版本号没有发生改变,则说明该Document在该原子事件中没有被其他请求所更新,可以顺利进行写入,并修改版本号;但如果版本号发生改变,则说明该Document在更新发生之前已被其他请求所更新, 由此便触发了一次“写冲突”。不过,在遇到写冲突以后,WiredTiger也会自动重试更新操作。

参考链接

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • FastJSON 源码分析

    Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java...

    Yano_nankai
  • 思维导图学 Spring

    思维导图使用 Xmind 制作,是记录 极客时间 丁雪峰 玩转Spring全家桶。

    Yano_nankai
  • 《Java编程思想》思维导图之 「第2章 一切都是对象」

    Yano_nankai
  • Android SystemUI(二):启动流程和初始化

    菜天哥哥
  • 一句话木马的各种变形

    一句话木马短小精悍,而且功能强大,隐蔽性非常好,在入侵中始终扮演着强大的作用。一句话木马一直在跟杀软斗智斗勇,出现一种,杀软秒更新规则。木马再变形,再被...

    洛米唯熊
  • 手机软件丨控雨控雪技能,一个手机就可以搞定

    《mixv控雨苹果版》是一款功能强大的手机视频编辑工具。软件拥有控雨,控雪的功能,用户可以利用此软件编辑各种自己酷炫的视频,软件中还拥有丰富的涂鸦贴纸,各种滤镜...

    半夜喝可乐
  • CephFS源码分析

    Lucien168
  • 一篇文章汇总WWDC2016(图文详解)声明前言一、眼花缭乱的iOS 10二、名正言顺的macOS三、深度呼吸的watchOS四、语音遥控的tvOS总结图文详解

    VV木公子
  • ROS2机器人应用简明教程03工具

    在阅读本文前,请最好先阅读01文档和02安装,配置好基本使用环境,gedit不作介绍了。

    zhangrelay
  • Amazon如何白手起家建立起一个平台帝国?

    人称T客

扫码关注云+社区

领取腾讯云代金券