数据库 MongoDB
2024-03-24 21:23:52 0 举报
AI智能生成
数据库 MongoDB
作者其他创作
大纲/内容
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的,属于文档类型数据库。
文档(Document):MongoDB 中最基本的单元,由 BSON 键值对(key-value)组成,类似于关系型数据库中的行(Row)。
集合(Collection):一个集合可以包含多个文档,类似于关系型数据库中的表(Table)。
数据库(Database):一个数据库中可以包含多个集合,可以在 MongoDB 中创建多个数据库,类似于关系型数据库中的数据库(Database)。
MongoDB 中的记录就是一个 BSON 文档,它是由键值对组成的数据结构,类似于 JSON 对象,是 MongoDB 中的基本数据单元。
BSON [bee·sahn] 是 Binary JSON 的简称,是 JSON 文档的二进制表示,支持将文档和数组嵌入到其他文档和数组中,还包含允许表示不属于 JSON 规范的数据类型的扩展。
BJSON 的遍历速度优于 JSON,但 BJSON 需要更多的存储空间。
键不能含有 \\0(空字符)。这个字符用来表示键的结尾。
. 和 $ 有特别的意义,只有在特定环境下才能使用。
以下划线_开头的键是保留的(不是严格要求的)。
键命名规则
文档
MongoDB 集合存在于数据库中,没有固定的结构,也就是 无模式 的,这意味着可以往集合插入不同格式和类型的数据。
集合名不能是空字符串\"\"。
集合名不能含有 \\0 (空字符),这个字符表示集合名的结尾。
集合名不能以\"system.\"开头,这是为系统集合保留的前缀。
集合名必须以下划线或者字母符号开始,并且不能包含 $。
集合命名条件
集合
数据库用于存储所有集合,而集合又用于存储所有文档。一个 MongoDB 中可以创建多个数据库,每一个数据库都有自己的集合和权限。
admin : admin 数据库主要是保存 root 用户和角色。
local : local 数据库是不会被复制到其他分片的,因此可以用来存储本地单台服务器的任意 collection。
config : 当 MongoDB 使用分片设置时,config 数据库可用来保存分片的相关信息。
test : 默认创建的测试库,连接 mongod 服务时,如果不指定连接的具体数据库,默认就会连接到 test 数据库。
预留库
不能是空字符串\"\"。
不得含有' '(空格)、.、$、/、\\和 \\0 (空字符)。
应全部小写。
最多 64 字节。
数据库命名条件
数据库
存储结构
数据记录被存储为文档:MongoDB 中的记录就是一个 BSON 文档,它是由键值对组成的数据结构,类似于 JSON 对象,是 MongoDB 中的基本数据单元。
模式自由:集合的概念类似 MySQL 里的表,但它不需要定义任何模式,能够用更少的数据对象表现复杂的领域模型对象。
支持多种查询方式:MongoDB 查询 API 支持读写操作 (CRUD)以及数据聚合、文本搜索和地理空间查询。
支持 ACID 事务:NoSQL 数据库通常不支持事务,为了可扩展和高性能进行了权衡。但MongoDB 支持事务,同样具有 ACID 特性。
高效的二进制存储:存储在集合中的文档,是以键值对的形式存在的。
自带数据压缩功能:存储同样的数据所需的资源更少。
支持 mapreduce:通过分治的方式完成复杂的聚合任务。从 MongoDB 5.0 开始,推荐其替代方案 聚合管道。
支持多种类型的索引:MongoDB 支持多种类型的索引,包括单字段索引、复合索引、多键索引、哈希索引、文本索引、 地理位置索引等。
支持 failover:提供自动故障恢复的功能,主节点故障时,自动选举新的主节点,客户无感知。
支持分片集群:MongoDB 支持集群自动切分数据,让集群存储更多的数据,具备更强的性能。
支持存储大文件:MongoDB 的单文档存储空间要求不超过 16MB。提供了 GridFS 来进行分块存储。
特点
数据库的核心组件,负责管理数据在内存和磁盘中的存储方式。与 MySQL 一样,MongoDB 采用的也是 插件式的存储引擎架构。
最初默认是使用 MMAPV1 存储引擎,MongoDB4.x 版本不再支持 MMAPv1 存储引擎。
WiredTiger 存储引擎:自 MongoDB 3.2 以后,默认的存储引擎为 WiredTiger 存储引擎 。非常适合大多数工作负载,建议用于新部署。WiredTiger 提供文档级并发模型、检查点和数据压缩等功能。
In-Memory 存储引擎:In-Memory 存储引擎 在 MongoDB Enterprise 中可用。它不是将文档存储在磁盘上,而是将它们保留在内存中以获得更可预测的数据延迟。
MongoDB 3.0 提供了 可插拔的存储引擎 API ,允许第三方为 MongoDB 开发存储引擎,这点和 MySQL 也比较类似。
分类
默认使用 B+ 树作为其存储结构,还支持 LSM(Log Structured Merge) 树作为存储结构。
使用 B+ 树时,WiredTiger 以 page 为基本单位往磁盘读写数据。B+ 树的每个节点为一个 page。
root page(根节点):B+ 树的根节点。
internal page(内部节点):不实际存储数据的中间索引节点。
leaf page(叶子节点):真正存储数据的叶子节点,包含一个页头(page header)、块头(block header)和真正的数据(key/value)。
page分类
WiredTiger
存储引擎
将多个文档甚至是多个集合汇总到一起计算分析(比如求和、取最大值)并返回计算后的结果,这个过程被称为 聚合操作 。
聚合管道(Aggregation Pipeline):执行聚合操作的首选方法。
单一目的聚合方法(Single purpose aggregation methods):也就是单一作用的聚合函数比如 count()、distinct()、estimatedDocumentCount()。
mapreduce:通过分治的方式完成复杂的聚合任务。从 MongoDB 5.0 开始,推荐其替代方案 聚合管道。
由多个阶段组成,每个阶段在文档通过管道时转换文档。
接受一系列原始数据文档。
对这些文档进行一系列运算。
结果文档输出给下一个阶段。
工作流程
匹配操作符,用于对文档集合进行筛选。
$match
投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段。
$project
排序操作符,用于根据一个或多个字段对文档进行排序。
$sort
限制操作符,用于限制返回文档的数量。
$limit
跳过操作符,用于跳过指定数量的文档。
$skip
统计操作符,用于统计文档的数量。
$count
分组操作符,用于对文档集合进行分组。
$group
拆分操作符,用于将数组中的每一个值拆分为单独的文档。
$unwind
连接操作符,用于连接同一个数据库中另一个集合,并获取指定的文档,类似于 populate。
$lookup
操作符
聚合管道
聚合
NoSQL 数据库通常不支持事务,但 MongoDB 支持事务。
MongoDB 单文档原生支持原子性,也具备事务的特性。通常指的是 多文档 。
MongoDB 4.0 加入了对多文档 ACID 事务的支持,但只支持复制集部署模式下的 ACID 事务,也就是说事务的作用域限制为一个副本集内。
MongoDB 4.2 引入了 分布式事务 ,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
在大多数情况下,多文档事务比单文档写入会产生更大的性能成本。对于大部分场景来说,适当地对数据进行建模可以最大限度地减少对多文档事务的需求。
从 MongoDB 4.2 开始,多文档事务支持副本集和分片集群,其中:主节点使用 WiredTiger 存储引擎,同时从节点使用 WiredTiger 存储引擎或 In-Memory 存储引擎。在 MongoDB 4.0 中,只有使用 WiredTiger 存储引擎的副本集支持事务。
在 MongoDB 4.2 及更早版本中,你无法在事务中创建集合。从 MongoDB 4.4 开始,您可以在事务中创建集合和索引。
事务
借助 WiredTiger 存储引擎,MongoDB 支持对所有集合和索引进行压缩。压缩以额外的 CPU 为代价最大限度地减少存储使用。
Snappy:谷歌开源的压缩算法(压缩比 3 ~ 5 倍),WiredTiger 默认使用其对所有集合使用块压缩,对所有索引使用前缀压缩。
zlib:高度压缩算法,压缩比 5 ~ 7 倍。
Zstandard(简称 zstd):Facebook 开源的一种快速无损压缩算法,针对 zlib 级别的实时压缩场景和更好的压缩比,提供更高的压缩率和更低的 CPU 使用率,MongoDB 4.2 开始可用。
算法
WiredTiger 日志也会被压缩,默认使用的也是 Snappy 压缩算法。如果日志记录小于或等于 128 字节,WiredTiger 不会压缩该记录。
数据压缩
MongoDB 可以使用该索引来限制它必须检查的文档数量,以便提高查询效率。
单字段索引: 建立在单个字段上的索引,索引创建的排序顺序无所谓,MongoDB 可以头/尾开始遍历。
复合索引: 建立在多个字段上的索引,也可以称之为组合索引、联合索引。字段的顺序非常重要,且遵循左前缀原则。
多键索引:MongoDB 的一个字段可能是数组,在对这种字段创建索引(为数组的每个值创建索引)时,就是多键索引。
哈希索引:按数据的哈希值索引,用在哈希分片集群上。
文本索引: 支持对字符串内容的文本搜索查询。支持全文索引,但性能低下,暂不推荐。
地理位置索引: 基于经纬度的索引,适合 2D 和 3D 的位置查询。
唯一索引:确保索引字段不会存储重复值。
TTL 索引:TTL 索引提供了一个过期机制,允许为每一个文档设置一个过期时间,当一个文档达到预设的过期时间之后就会被删除。
TTL 索引是单字段索引。复合索引不支持 TTL。
_id字段不支持 TTL 索引。
无法在上限集合(Capped Collection)上创建 TTL 索引,因为 MongoDB 无法从上限集合中删除文档。
如果某个字段已经存在非 TTL 索引,那么在该字段上无法再创建 TTL 索引。
TTL 索引限制
所有的查询字段是索引的一部分。
结果中返回的所有字段都在同一索引中。
查询中没有字段等于null。
覆盖索引查询
索引
又称为副本集群,是一组维护相同数据集合的 mongod 进程。
一个复制集群包含 1 个主节点(Primary),多个从节点(Secondary)以及零个或 1 个仲裁节点(Arbiter)。
主节点:整个集群的写操作入口,接收所有的写操作,并将集合所有的变化记录到操作日志中,即 oplog。主节点挂掉之后会自动选出新的主节点。
从节点:从主节点同步数据,在主节点挂掉之后选举新节点。不过,从节点可以配置成 0 优先级,阻止它在选举中成为主节点。
仲裁节点:这个是为了节约资源或者多机房容灾用,只负责主节点选举时投票不存数据,保证能有节点获得多数赞成票。
组成
主节点与备节点之间是通过 oplog(操作日志) 来同步数据的。oplog 是 local 库下的一个特殊的 上限集合(Capped Collection) ,用来保存写操作所产生的增量日志,类似于 MySQL 中 的 Binlog。
实现 failover:提供自动故障恢复的功能。
实现读写分离:减轻了主节点读写压力过大的问题。
优势
复制集群
MongoDB 的分布式版本,相较副本集,分片集群数据被均衡的分布在不同分片中。
不仅大幅提升了整个集群的数据容量上限,也将读写的压力分散到不同分片,以解决副本集性能瓶颈的难题。
作用
Config Servers:配置服务器,本质上是一个 MongoDB 的副本集,负责存储集群的各种元数据和配置,如分片地址、Chunks 等。
Mongos:路由服务,不存具体数据,从 Config 获取集群配置讲请求转发到特定的分片,并且整合分片结果返回给客户端。
Shard:每个分片是整体数据的一部分子集,从 MongoDB3.6 版本开始,每个 Shard 必须部署为副本集(replica set)架构。
垂直扩展:通过增加单个服务器的能力来实现,比如磁盘空间、内存容量、CPU 数量等。
水平扩展:通过将数据存储到多个服务器上来实现,根据需要添加额外的服务器以增加容量。
拓展方式
存储容量受单机限制,即磁盘资源遭遇瓶颈。
读写能力受单机限制,可能是 CPU、内存或者网卡等资源遭遇瓶颈,导致读写能力无法扩展。
场景
分片键(Shard Key) 是数据分区的前提, 从而实现数据分发到不同服务器上,减轻服务器的负担。
分片键就是文档里面的一个字段,但是这个字段不是普通的字段,有一定的要求。
它必须在所有文档中都出现。
它必须是集合的一个索引,可以是单索引或复合索引的前缀索引,不能是多索引、文本索引或地理空间位置索引。
MongoDB 4.2 之前的版本,文档的分片键字段值不可变。MongoDB 4.2 版本开始,除非分片键字段是不可变的 _id 字段,否则您可以更新文档的分片键值。MongoDB 5.0 版本开始,实现了实时重新分片(live resharding),可以实现分片键的完全重新选择。
它的大小不能超过 512 字节。
要求
选择合适的片键对 sharding 效率影响很大,主要基于四个因素。
取值基数:取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。
取值分布:取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
查询带分片:查询时建议带上分片,使用分片键进行条件查询时,可以直接定位到具体分片,否则需要将查询分发到所有分片,再等待响应返回。
避免单调递增或递减:单调递增的 sharding key,数据文件挪动小,但写入会集中,导致最后一篇的数据量持续增大,不断发生迁移,递减同理。
选择条件
分片键
MongoDB 按照分片键(Shard Key)的值的范围将数据拆分为不同的块(Chunk),每个块包含了一段范围内的数据。当分片键的基数大、频率低且值非单调变更时,范围分片更高效。
Mongos 可以快速定位请求需要的数据,并将请求转发到相应的 Shard 节点中。
优点
可能导致数据在 Shard 节点上分布不均衡,容易造成读写热点,且不具备写分散性。
缺点
分片键的值不是单调递增或单调递减、分片键的值基数大且重复的频率低、需要范围查询等业务场景。
基于范围的分片
MongoDB 计算单个字段的哈希值作为索引值,并以哈希值的范围将数据拆分为不同的块(Chunk)。
可以将数据更加均衡地分布在各 Shard 节点中,具备写分散性。
不适合进行范围查询,进行范围查询时,需要将读请求分发到所有的 Shard 节点。
分片键的值存在单调递增或递减、片键的值基数大且重复的频率低、需要写入的数据随机分发、数据读取随机性较大等业务场景。
基于 Hash 值的分片
除了上述两种分片策略,还可以配置 复合片键 ,例如由一个低基数的键和一个单调递增的键组成。
分片策略
MongoDB 分片集群的一个核心概念,其本质上就是由一组 Document 组成的逻辑数据单元。每个 Chunk 包含一定范围片键的数据,互不相交且并集为全部数据,即离散数学中划分的概念。
Chunk(块)
分片集群不会记录每条数据在哪个分片上,而是记录 Chunk 在哪个分片上一级这个 Chunk 包含哪些数据。
默认情况下,一个 Chunk 的最大值默认为 64MB(可调整,取值范围为 1~1024 MB。如无特殊需求,建议保持默认值)。
进行数据插入、更新、删除时,如果此时 Mongos 感知到了目标 Chunk 的大小或者其中的数据量超过上限,则会触发 Chunk 分裂。
Chunk 分裂
数据的增长会让 Chunk 分裂得越来越多。此时各个分片上的 Chunk 数量可能会不平衡。Mongos 中的 均衡器(Balancer) 组件就会执行自动平衡,尝试使各个 Shard 上 Chunk 的数量保持均衡,这个过程就是 再平衡(Rebalance)。默认情况下,数据库和集合的 Rebalance 是开启的。
Rebalance 操作是比较耗费系统资源的,我们可以通过在业务低峰期执行、预分片或者设置 Rebalance 时间窗等方式来减少其影响。
再平衡(Rebalance)
MongoDB默认情况下会开启一个balancer模块用于定期检测各个shard上的chunk数量分布,当检测到各个shard上的chunk数量存在分布不均匀的情况时,就会触发chunk迁移。
chunk迁移操作通过moveChunk命令发起,可以被balancer自动调用(balancer每隔10s扫描哪些chunk需要被迁移),也支持用户主动发起。
迁移chunk的整个过程实际上就是一次两个shard进行数据交换的过程,分别有 chunk 的发送方和接收方。
Chunk 迁移
分片数据存储
分片集群
高可用
MongoDB 的优势在于其数据模型和存储引擎的灵活性、架构的可扩展性以及对强大的索引支持。
应用
数据库 MongoDB
0 条评论
回复 删除
下一页