关键字
上限集合(Capped Collection)
上限集合类似于定长的循环队列,数据顺序追加到集合的尾部,当集合空间达到上限时,它会覆盖集合中最旧的文档。上限集合的数据将会被顺序写入到磁盘的固定空间内,所以,I/O 速度非常快,如果不建立索引,性能更好。
分片
副本
链式复制、非链式复制
高可用-复制集群
Primary 节点
Secondary 节点
Arbitoer 节点(仲裁节点)
高伸缩-分片集群
MongoDB 的分布式版本,用于提升集群的数据容量,读吞吐量,分散读写压力
configserver:配置服务
shard:分片服务
mongdos:路由服务
分片键(Shard Key):
决定了分片数据在分片中的分布情况
Chunk(块):
分片集群的一个概念,本质上就是一堆 Document 的逻辑数据单元,每个 Chunk 包含一定范围的片键的数据
属于离散数学中的划分概念
均衡器(Balancer) 、再平衡:
chunk 分裂的过程
GridFS:支持超大文件分片存储
写关注(Write Concern):
用来描述数据库写操作返回信息的保证级别,有3种选项,分别为0 - Unacknowledged、1 - Acknowledged、 majority - Replica Acknowledged,
概述
什么是 MongoDB
由C++语言编写,基于分布式文件存储的,介于关系数据库与非关系数据库
特点
它是一种面向集合,模式无关的文档型数据库。其中数据以“集合”的方式进行分组,每个集合都有单独的名称并可以包含无限数量的文档。这里的集合同关系型数据库中的表(table)类似,唯一的区别就是它并没有任何明确的schema。 MongoDB以一系列键值对集合的方式存储数据,其中键(Key)是字符串,值(Value)是任何一种数据类型的集合,包括数组和文档。
适用场景
原理
索引类型有哪些?
- 单字段索引(
Single Field Indexes
) - 复合索引(
Compound Indexes
) - 多键索引(
Multikey Indexes
) - 全文索引(
text Indexes
) - Hash 索引(
Hash Indexes
) - 通配符索引(
Wildcard Index
) - 2dsphere索引(
2dsphere Indexes
)
索引的限制
额外的开销:
索引是存放在内存中的:当内存不够时,会删掉一些索引
在正则和非操作符($nin、$not 等)、算数操作符、$where 子句中不会使用索引
引擎
MMAP(内存映射)
3.0 版本之前,只有这一种
锁颗粒度较粗
基于填充因子的自适应分配方式(paddingFactor),这种方式下将会基于每个集合计算历史的文档更新平均增长长度,每当新文档插入或者老文档移动,都会基于填充因子推算出额外空间填充进去。MMAP还提供了一种基于usePowerOf2Sizes的预分配方式,这种方式直接为文档分配2的N次方大小的存储空间。
将所有文件、索引存储到了一起,不利于磁盘空间回收
MMAPv1
3.0 版本之后
锁颗粒较细(库级别 -> 集合级别)
将基于usePowerOf2Sizes的预分配方式作为默认的文档空间分配方式
创建集合的时候还可以设置成noPadding标签,关闭空间预分配。
WiredTiger(重点,类 b+树)
锁粒度进一步细化(集合级别 -> 文档级别),类似于 MySQL 中的行锁了
压缩算法
支持对所有集合和索引进行块压缩和前缀压缩,包括journal日志,
- Snappy(默认):压缩速度快,cpu 开销低,适合大多数业务场景
- Zlib:压缩率高,但是速度慢
- none(不压缩)
文件格式:
集合、索引存放到单独的文件中,便于删除后及时释放空间
原理
以 page 为单位向磁盘中写数据,每个 page 是 b+树中的一个节点
官网讲解文档:
写入流程
WiredTiger的写操作会先写入Cache,并持久化到WAL(Write ahead log),每60s或log文件达到2GB时会做一次Checkpoint,将当前的数据持久化,产生一个新的快照。Wiredtiger连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性。
写关注(Write Concern):
用来描述数据库写操作返回信息的保证级别,有3种选项,分别为0 - Unacknowledged、1 - Acknowledged、 majority - Replica Acknowledged
修改流程
原理是修改的时候,会生成新的节点,不修改原有的节点
会导致 b+树越来越大,但是写入性能强(空间换时间)
MongoRocks
基于 facebook 开源的 rocksDB 实现的存储引擎
最大的特点:支持高并发随机写入和读取
压缩算法更多:
Snappy、Zlib和LZ4等压缩算法
In-Memory(官方企业版)
其他特殊版本
架构
副本集群
支持数据一致性要求强、要求不强的场景
即 MongoDB 的高可用解决方案
通过 opLog 的复制来实现数据同步和最终一致性
类似 MySQL 的 binlog,但 binLog 是二进制文件;但是 opLog 是 MongoDB 的一个特殊集合,叫capped collection
这种集合在创建初期就设置其大小或者文档最大数量,后续按照LRU(Least Recently Used)规则和插入顺序进行 age-out。
opLog 的特点:
- 可插入和更新,更新不能超出文档大小,否则更新失败;
- 不可以删除文档,只能删除整个集合;
- 32bit系统上大小有限制,而64bit系统则无文件大小限制;
- 在这个集合上无法进行分片;
副本集的特点:
- MongoDB副本集拥有具备各种功能的多种角色,比如投票节点、隐藏从库、延迟从库等;
- MongoDB可配置每个成员的优先级(priority)和投票数(votes),以此来建设异地容灾集群,比如我就指定某地域只能选主,其他地域只提供读服务;
- 结合强大的MongoDB驱动实现读写分离、强一致。
分片集群
水平扩容的一种
支持自动分片、手动分片
自动预分片支持:如果分片集群选用 hash 分片策略,则支持 shardCollection 时提前对片建进行自动预备分片。
手动预分片支持:hash 分片策略和范围分片策略都可以通过 mongodb 自有的 splitAt 等接口进行手动人工预分片,分片接口的支持确保预分片更加弹性自由。
组成
- Config Servers:配置服务器,本质上是一个 MongoDB 的副本集,负责存储集群的各种元数据和配置,如分片地址、Chunks 等
- Mongos:路由服务,不存具体数据,从 Config 获取集群配置讲请求转发到特定的分片,并且整合分片结果返回给客户端。
- Shard:每个分片是整体数据的一部分子集,从 MongoDB3.6 版本开始,每个 Shard 必须部署为副本集(replica set)架构
分片键:
要求得是文档的字段
且是一个索引(不能是多索引、文本索引、地理空间索引)
5.0 之后,分片键实时可变
大小不能超过 512 字节
选择要求:
- 取值基数 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如:选择年龄做一个基数,范围最多只有 100 个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk,从而无法迁移,导致数据分布不均匀,性能瓶颈。
- 取值分布 取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
- 查询带分片 查询时建议带上分片,使用分片键进行条件查询时,mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。
- 避免单调递增或递减 单调递增的 sharding key,数据文件挪动小,但写入会集中,导致最后一篇的数据量持续增大,不断发生迁移,递减同理。
分片策略
- 基于 hash 分片
- 基于范围分片
Chunk
分片集群不会记录每条数据在哪个分片上,而是记录 Chunk 在哪个分片上一级这个 Chunk 包含哪些数据。
默认情况下,一个 Chunk 的最大值默认为 64MB(可调整,取值范围为 1~1024 MB。如无特殊需求,建议保持默认值),进行数据插入、更新、删除时,如果此时 Mongos 感知到了目标 Chunk 的大小或者其中的数据量超过上限,则会触发 Chunk 分裂。
数据的增长会让 Chunk 分裂得越来越多。这个时候,各个分片上的 Chunk 数量可能会不平衡。Mongos 中的 均衡器(Balancer) 组件就会执行自动平衡,尝试使各个 Shard 上 Chunk 的数量保持均衡,这个过程就是 再平衡(Rebalance)。默认情况下,数据库和集合的 Rebalance 是开启的。
优点
- 架构简单
- 没有复杂的连接
- 深度查询能力,
<font style="color:rgb(255, 80, 44);background-color:rgb(255, 245, 245);">MongoDB</font>
支持动态查询。 - 容易调试
- 容易扩展
- 不需要转化/映射应用对象到数据库对象
- 使用内部内存作为存储工作区,以便更快的存取数据。
MongoDB 本身可能存在的问题
1、opLog 循环复制问题
集团的 MongDB 打了补丁,修改了 opLog 的格式
2、opLog 不支持 回滚?
给 opLog 加上了全镜像功能
与其他产品的对比
形式 | MongoDB | MySQL |
---|---|---|
数据库模型 | 非关系型 | 关系型 |
存储方式 | 虚拟内存+持久化 | |
查询语句 | 独特的MongoDB查询方式 | 传统SQL语句 |
架构特点 | 副本集以及分片 | 常见单点、M-S、MHA、MMM等架构方式 |
数据处理方式 | 基于内存,将热数据存在物理内存中,从而达到高速读写 | 不同的引擎拥有自己的特点 |
使用场景 | 事件的记录,内容管理或者博客平台等数据大且非结构化数据的场景 | 适用于数据量少且很多结构化数据 |
形式 | MongoDB | redis |
---|---|---|
内存管理机制 | MongoDB 数据存在内存,由 linux系统 mmap 实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘 | Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据 |
支持的数据结构 | MongoDB 数据结构比较单一,但是支持丰富的数据表达,索引 | Redis 支持的数据结构丰富,包括hash、set、list等 |
性能 | mongodb依赖内存,TPS较高 | Redis依赖内存,TPS非常高。性能上Redis优于MongoDB |
可靠性 | 支持持久化以及复制集增加可靠性 | Redis依赖快照进行持久化;AOF增强可靠性;增强可靠性的同时,影响访问性能 |
数据分析 | mongodb内置数据分析功能(mapreduce) | Redis不支持 |
事务支持情况 | 只支持单文档事务,需要复杂事务支持的场景暂时不适合 | Redis 事务支持比较弱,只能保证事务中的每个操作连续执行 |
集群 | MongoDB 集群技术比较成熟 | Redis从3.0开始支持集群 |
参考
1、https://juejin.cn/post/6844903965629349895
3、【【驳斥八股文系列】别瞎分析了,MongoDB 使用的是 B+ 树,不是你们以为的 B 树】https://zhuanlan.zhihu.com/p/519658576
4、https://javaguide.cn/database/mongodb/mongodb-questions-02.html#%E5%88%86%E7%89%87%E9%9B%86%E7%BE%A4