MongoDB的分片集群(一) : 基础知识

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。


 

目录导读

1. 什么是MongoDB分片
2. MongoDB分片集群介绍
    2.1 MongoDB分片集群架构
    2.2 MongoDB分片集群优势
3. 分片键的选择
    3.1 选择基数大的分片键
    3.2 选择分布均匀的分片键
    3.3 避免单调增加或减少的分片
    3.4 分片键涵盖最常用的查询模式
4. 分片的策略
    4.1 哈希分片
    4.2 范围分片(远程分片)
    4.3 分区分片
5. 分片前的注意事项

1. 什么是MongoDB分片

分片是一种将数据分布在多个机器,MongoDB使用分片来支持具有非常大数据的部署集和高吞吐量操作。

具有大型数据集或高吞吐量应用程序的数据库系统会给单个服务器的容量带来挑战。例如,高查询率可以耗尽服务器的 CPU 容量;工作集大小大于系统的 RAM 会给磁盘驱动器的 I/O 容量带来压力。
有两种方法可以解决系统增长问题:垂直和水平缩放。
垂直扩展:增加单个服务器的容量,例如 如使用更强大的 CPU、添加更多 RAM 或增加 存储空间。但单个服务器的CPU、RAM终有天花板值,不能无限扩张。因此,垂直缩放有一个实际最大值。
水平扩展:划分系统数据集并加载多台服务器,根据需要增加服务器节点数量以增加容量。虽然单台机器的整体速度或容量可能不高,但每台机器处理整体工作负载的子集,可能提供更好的比单个高速高容量服务器的效率。扩展部署容量只需要根据需要添加额外的服务器, 这可能比单台机器的高端硬件更低的总成本。代价是基础设施和维护的复杂性增加部署。

2. MongoDB分片集群介绍

2.1 MongoDB分片集群架构

一个MongoDB分片集群由以下组件组成:

shard每个分片包含一个分片数据的子集。每个分片都可以部署为副本集。

mongos:查询路由器,是个无状态应用。负责接收客户端的请求并将其路由到正确的分片上,进行读写合并多个数据节点的返回。本身不存储数据,也不维护任何与客户数据相关的状态信息。建议部署2个及以上节点。从MongoDB4.4开始,可以支持hedged reads 以最大程度地减少延迟。

config servers:confi服务器负责存储和管理分片集群的元数据信息,如分片键范围、分片集群配置等。官方建议最少部署3个config服务器且部署为副本集。另外,因投票选举机制,config服务器数量建议为奇数。

hedged reads技术是一种优化读取操作的方式,以最小化延迟。hedged reads技术是通过同时向多个分片服务器发出查询请求,然后使用最先返回结果的服务器来响应查询请求,从而实现最小化延迟的。这种技术通常用于高负载的环境中,以提高查询性能和响应时间。

MongoDB在collection级别对数据进行分片,通过集群中的分片分发collection数据。

2.2 MongoDB分片集群优势

1)读写

MongoDB 在分片集群中的分片之间分配读写工作负载,允许每个分片处理集群操作的子集。读取和写入工作负载都可以通过添加更多分片在集群中水平扩展。

对于包含shard key或复合shard key前缀的查询,mongos可以针对特定的shard或shard集合进行查询。这些有针对性的操作通常比广播到集群中的每个分片更有效。

从MongoDB4.4开始,可以支持hedged reads 以最大程度地减少延迟。

2)存储容量

分片将数据分布在集群中的多个分片上,允许每个分片包含集群总数据的一个子集。随着数据集的增长,额外的分片会增加集群的存储容量。

3)高可用性

config server服务器和副本集式部署的分片提供了高可用性:

即使一个或多个分片复制集完全不可用,分片集群也可以继续执行部分读写操作。也就是说,当不可用分片上的数据不能被访问时,对可用分片的读写仍然可以成功。

注意:不是所有的集群都适用于分片集群。比如数据量小的场景,就完全没必要用分片集群了

3. 分片键的选择

MongoDB 使用分片键来跨分片分发collection的文档。分片键由文档中的一个或多个字段组成。

在版本 4.2 及更早版本中,分片集合的每个文档中都必须存在分片键字段。

从版本 4.4 开始,分片集合中的文档可以是缺少分片键字段。在跨分片分布文档时,缺少的分片键字段将被视为具有空值,但在路由查询时则不被视为具有空值。

例如一条分片语句:

sh.shardCollection("your_database_name.your_collection_name", { "shard_key": "hashed" })
#如:
sh.shardCollection("dbtest.collectiontest", { "shard_key": "hashed" })

选择分片键(shard_key)要考虑的几个因素:

分片键的基数;

分片键值出现的频率,尽可能被更多的业务场景使用;

潜在的分片键是否单调增长/减小;

分片查询模式;

Shard Key限制;

在对集合进行分片时,选择合适的分片键:

在 MongoDB 4.2 及更早版本中,一旦对一个集合进行了分片,那么分片键的选择是不可变的。

从 MongoDB 4.4 开始,可以通过refineCollectionShardKey命令来优化分片键;通过refineCollectionShardKey命令向现有键添加一个或多个后缀字段,以创建新的分片键。

从MongoDB 5.0开始,可以通过使用reshardCollection命令更改分片键来重新分片collection。

文档的分片键value值决定了它在分片中的分布

在MongoDB 4.0及更早版本中,文档的分片键字段value值是不可变的。

从MongoDB 4.2开始,可以更新文档的分片键value值,除非使用的分片键字段是不可变的_id字段。

3.1 选择基数大的分片键

几个概念及关系:

1)集群 Cluster: 一个cluster 包含 n 个shard

2)分片 Shard:一个shard 包含 n 个 chunk

3)块 Chunk :一个chunk 包含 n 个doc

4)文档 doc :一个doc包含一个 shard key,该值决定了文档所属的Chunk及存储该文档的Shard。

5)分片键 shard key:文档中的一个字段

在任何给定时间,每个唯一的shard键值只能存在于一个块中。分片键的基数决定了平衡器可以创建的最大块数量。因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,水平扩展时移动块会非常困难。因此,建议选择基数大的分片键。如果当前的数据模型需要对基数低的键进行分片,可考虑使用索引复合字段来增加基数。

例如:

如果根据性别来进行分片,则分片的基数为2。基数为2意味着在分片集群中不能有超过2个块(chunk),每个块存储一个唯一的分片键值。这也将集群中有效分片的数量限制在2个,添加更多的分片也不会带来更多的效用。

选择基数小的分片键,插入数据可能会产生这种效果:

3.2 选择分布均匀的分片键

分片键的频率代表了给定的分片键值在数据中出现的频率。如果这个频率分布不均匀,存储具有这些值的文档的块的数据量可能会急剧增大,这些块的压力随之增大。而数据均衡又以 chunk 为单位,这些压力巨大的chunk没有办法被别的chunk分担,所以可能成为集群中的瓶颈。

因此建议选择在数据中出现频率分布均匀的分片键。如果当前的数据模型需要对具有高频次出现的键进行分片,可考虑使用使用唯一值或低频值的复合索引。

例如:

存储一个城市所有小学5年级学生的数据,数据范围是9-16岁,以年龄整数进行分片,分片基数为8,有8个chunk。但根据我国小学入学条件规定,大部分小学五年级学生的年龄绝大部分集中在10岁和11岁,就会导致10岁的chunk和11岁的chunk的读写压力增大,成为瓶颈。而别的chunk可能一个数据都没有,没有读写压力。

选择频率出现高低不均的分片键,插入数据可能会产生这种效果:

3.3 避免单调增加或减少的分片键

分片键避免使用单调增加或减少的分片键。如果当前数据模型需要对单调变化的键进行分片,可考虑使用哈希分片。

一个值单调增加或减少的分片键更有可能将写入的数据分发到集群中的单个块上。

这是因为每个集群都有一个块,它捕获一个具有maxKey上限的范围。maxKey总是比所有其他值高。类似地,有一个块捕获minKey下界的范围。minKey总是比所有其他值低。

如果分片键值一直在增加,那么所有新的插入数据都将以maxKey为上界路由到捕获maxKey上限的块中。如果分片键值一直在减小,那么所有新的插入数据都将以minKey作为下界路由到捕获minKey下界的块中。包含该块的分片就将成为写入操作的瓶颈。

为了优化数据分布,包含全局maxKey(或minKey)的块不会留在同一个分片上。当分割块时,具有maxKey(或minKey)块的新块位于不同的分片上。

下图展示了一个使用字段X作为分片键的分片集群。如果X的值单调增加或减小的场景下,则插入的分布可能类似于以下情况:

3.4 分片键涵盖最常用的查询模式

理想的分片键在整个分片集群中均匀分布数据,同时还支持通用查询模式。因此在选择分片键时,先考虑整个数据集中最常见的查询模式有哪些,给定的分片键是否涵盖了这些模式。

在分片集群中,如果查询包含shard key, mongos只会将查询路由到包含相关数据的shard。当查询不包含分片键时,查询将广播到所有分片进行评估。这些类型的查询称为分散-收集查询。对于每个请求涉及多个分片的查询效率较低,并且当向集群添加更多分片时不能线性扩展。这不适用于对大量数据进行操作的聚合查询。

在某些特殊情况下,分散-收集可能是一种有用的方法,它允许查询在所有分片上并行运行。

4. 分片的策略

MongoDB支持两种分片策略,用于跨分片集群分发数据。

4.1 哈希分片

哈希分片将数据通过哈希函数计算得到哈希值,然后根据哈希值为每个块分配一个范围。MongoDB在使用哈希索引解析查询时自动计算哈希值。应用程序不需要计算哈希值。

基于哈希值的分片有助于更均匀的进行数据分布,特别是在分片键单调变化的数据集中。比较适用于高并发场景。

然而,哈希分布意味着对分片键的查询不太可能针对单个分片,而是在更多的集群范围内进行广播操作,降低查询操作效率。

4.2 范围分片(远程分片)

范围分片(远程分片)根据分片键值将数据划分为不同的范围。然后根据分片键值为每个块分配一个范围:

一组分片键值接近的分片键更有可能分配在同一个块上。这就允许有某些针对性的操作,因为mongos可以将操作路由到包含所需数据的分片。

范围分片的效率取决于所选择的分片键。范围分片将数据按指定的范围进行划分,使得在进行范围查询时能够只在涉及的分片上执行查询操作,不需要访问整个分片集群,减少了数据在网络中的传输,提高了范围查询的性能。

但考虑不当的分片键可能导致数据分布不均匀,容易出现热点,可能导致性能瓶颈。

4.3 分区分片

分片集群跨多个数据中心时,区域可以帮助提高数据的本地性。

在分片集群中,可以根据shard key创建分片数据分区。可以将每个分区与集群中的一个或多个分片关联,一个shard可以与任意数量的zone相关联。

在balance集群时,MongoDB只会将一个区域覆盖的块迁移到与该区域关联的那些分片上。

每个区域包含一个或多个分片键值范围。一个区域覆盖的每一个范围总是包括它的下边界而不包括它的上边界。

5. 分片前的注意事项

分片集群基础设施的需求和复杂性需要仔细规划、执行和维护。如分片集群架构、服务器数量、配置等相关事项。

一旦对一个集合进行了分片,MongoDB目前没有任何方法来对这个被分片的集合进行反分片。虽然可以重新对集合进行切分,但务必仔细考虑切分键的选择,以避免出现可伸缩性和性能问题。

一个数据库(如db:test)可以混合使用分片集合(collection)和非分片集合(collection)。分片集合(collection)在集群中的多个分片之间进行分区和分布。未分片的集合(collection)存储在主分片上。每个数据库都有自己的主分片。

连接到分片集群:

连接到mongod的方式有两种:通过mongosh连接或者MongoDB驱动连接。这两种方式同样适用于连接到mongos。

以上即MongoDB分片集群的简要梳理总结。

参考文档:Sharding — MongoDB Manual

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/450467.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++核心deque容器,stack容器,queue容器,list容器,set容器,pair ,map容器

3.deque容器 1.deque容器的基本概念 Vector容器是单向开口的连续内存空间,deque则是一种双向开口的连续线性空间。所谓的双向开口,意思是可以在头尾两端插入元素,但是在其头部操作效率奇差,无法被接受。 deque容器和vector容器最…

Go语言编写安全的HTTP代理服务器

在构建HTTP代理服务器时,安全性是一个不可忽视的重要因素。使用Go语言编写代理服务器可以确保较高的性能和并发性,同时通过一些关键的安全措施,可以增强服务器的安全性。 加密通信: 使用HTTPS:HTTPS通过TLS/SSL协议对…

PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?

问题: PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?PostgreSQL 能否替代 MySQL? 当我们讨论为何 MySQL 在中国大陆成为主流而 PostgreSQL 屈居二线时, 我们其实…

环形链表(快慢指针)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环…

TQ15EG开发板教程:使用vivado2023.1实现LWIP的网络传输

使用vivado2023.1实现LWIP的网络传输 创建工程模板在hello_world中已经介绍过了,这里直接从配置完zynq ip核开始 配置好IP核后,右键设计模块,点击Generate Output ... 右键设计模块生成HDL文件,本工程不会使用到bit文件所以不用生…

睿尔曼6自由度机械臂ROS驱动包功能拓展之查询指令

1:主要环境预览 1:系统:Ubuntu 20.04 2:ROS:noetic 3:对于系统要求需根据相关手册完成机械臂相关依赖安装,能够运行机械臂本身基本功能, 包括 moveit。 4:准备资料…

Golang的数字签名之旅:crypto/ecdsa库详解

Golang的数字签名之旅:crypto/ecdsa库详解 引言crypto/ecdsa库概览基本功能安装和设置使用场景 ECDSA原理简介椭圆曲线密码学基础ECDSA的工作原理安全性考虑 Golang中ECDSA的实现密钥生成数字签名签名验证 crypto/ecdsa的高级应用性能优化安全性考虑实际应用案例 总…

echarts条形图添加滚动条

效果展示: 测试数据: taskList:[{majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {maj…

备战蓝桥杯---搜索(应用基础1)

话不多说&#xff0c;直接看题&#xff1a; 显然&#xff0c;我们直接用深搜&#xff0c;我们可以先把空位用结构体存&#xff0c;然后打表存小方块&#xff0c;再用数组存行列。 下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; int a[12][12];…

2024美赛A题七鳃鳗种群复杂系统动力学模型完整成品论文和代码

经过不懈的努力&#xff0c;2024美赛A题完整成品论文和代码已完成&#xff0c;代码为A题全部4问的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1七鳃鳗种群竞争模型的建立和求解、问题2种群优势劣势评估模型的建立…

Spring 事务原理总结三

今天这篇文章&#xff0c;我想梳理一下Spring事务用到的几个核心组件。这些核心组件是我们理解Spring事务原理的基础。通过它们我们可以体会学习一下Spring设计者设计Spring事务时的基本思路。这些组件是&#xff1a;TransactionInfo、TransactionStatus、TransactionManager、…

数学建模比赛期间,网上的各种思路靠谱吗

美赛第二天&#xff0c;很多人已经撑不住了。 从昨天起网上就那么多“思路”、“指导”、“代做”、“成品论文”&#xff0c;有免费的&#xff0c;也有收钱的。 有人说那些思路都是滥竽充数&#xff0c;纯坑钱浪费时间 有人说自己啥都不会&#xff0c;看那些思路就有启发 有…