首页 > 数据库 >【MongoDB】shard切分 原理

【MongoDB】shard切分 原理

时间:2022-11-11 12:07:55浏览次数:51  
标签:一个 MongoDB chunk shard 切分 哈希 片键


1.角色:

在一个MongoDB的shard集群中,会有三种角色:shard,config和routing

shard:每一个shard节点都会包含数据集的一部分,是存储真正数据的节点;

config:主要存储元数据或者配置信息,比如每一个切片的片键的范围,mongos(即routing)会根据这个服务器的配置信息来决定到哪一个分片服务器上存取数据

routing:也就是mongos客户端,用来操作shard集群的接口。

这里有一个问题,为什么不把集群信息存储在mongos里面,即由mongos客户端进程来管理维护呢?主要是因为这些配置信息是会动态改变的,因此直接交给另一个进程更好。

【MongoDB】shard切分 原理_分片

通常,每一个shard都会是一个复制集,主要为了健壮性,因为切片集群一个挂一个切片,那么整个切片的数据都会丢失。每一个config更应该是一个复制集,因为一旦config挂了,那么整个集群就用不了了,所以在MongoDB的最新版本中,强制配置config节点为至少3个节点的复制集,这是很有必要的。


2.片键:

指的就是文档中的一组属性,mongos会根据这个属性来查看该条数据应该属于哪一个shard分片。片键的路由有两种实现方式,一种是范围,一种是哈希,其实本质上都是范围。

范围法:把片键的取值划分为很多区间,每一个区间对应一个分片(其实是chunk,后面再说);

【MongoDB】shard切分 原理_扩展_02


哈希法:先根据片键值计算哈希值,然后把哈希值按范围划分,只是比范围法多了一步哈希。使用哈希法可以使得键值分布更加均匀。

【MongoDB】shard切分 原理_分布式存储_03


3.chunk,块,理解这个概念很重要。块是比分片更小的单位,每一个shard分片都是由若干个chunk构成的,chunk有以下一些属性:

min和max,该chunk里最小和最大的片键,也就是这个chunk的数据范围,这其实是对应了我们之前说的片键区间。片键的每一个区间段都会对应一个chunk。每一个shard的配置信息就会包括其中所有的chunk块的范围,最终mongos就可以根据这些值来判定应该走哪一个切片的哪一个chunk。

maxSize,chunk大小的上限,这个和后面的内容有关,是一个阈值,会触发chunk的分割。


4.chunk分裂:

MongoDB不希望chunk块的size太大,所以一旦超过了maxSize,就会执行一次split操作,把chunk分割为几个更小的chunk。当发生insert或者update操作时,可能会除触发split操作。


5.balancer:

balancer是MongoDB里的一个后台进程,会检测每一个分片的chunk数目,一旦发现某一些分片的chunk数目太多,就会触发一次chunkMove,会把多出来的chunk移到chunk较少的分片上。每当chunk太大被分裂时,就很有可能导致某一个分片上的chunk数目变多,触发move。当我们增加或者删除shard机器时,也会导致上述move过程。

过程如下:balancer会给要迁移的shard发出一个move命令,该shard就会发送自己的数据给目标shard,目标shard就会同步数据,一旦同步完,源shard就会删除数据,最后config里面的配置信息也会被更新。

所以,MongoDB的shard集群为用户提供了一种水平扩展数据的功能,还提供了健壮性和可用性,健壮性是我们可以使用复制集技术来增加容错性,可用性是我们可以随意修改shard集群的节点,shard集群内部会做相应的balance,让每一个shard的空间都均摊所有的数据,其实这个还是很重要的,因为虽然我们可以部署很多机器,但是一旦最后的数据分布-不均匀,全部到了一台机器上,导致这个机器负载太高,装不下数据,应用肯定会挂,但是其余的机器却是空的,所以这里的balance功能非常重要。

实现思路大致是,首先保证每一个shard的chunk数目相当,但是光有这一点还不行,因为可能某一些chunk很大,所以还必须保证每一个chunk的大小均匀,这是通过split来实现,基于这两点,就可以保证每一个shard的大小相当。为什么shard的数据要以一个一个的chunk来组织?如果不以chunk来组织,那么如果要平衡数据,只能以shard为视角,把shard的一部分数据移到另一个shard,表面上好像也没什么,甚至更简单,但是实际上,比较难做到,因为当我们想把一个shard的一部分切下来时,该如何修改shard的片键范围呢?这是比较复杂的问题,切分的大小和片键的范围没有一一对应的关系,所以MongoDB就想出了让shard以chunk来做平衡的单位,每一个chunk会对应一个子区间,chunk本身有自己的大小管理,比如分裂,所以每一个shard里面的chunk基本可以认为大小一样,这样shard做平衡的依据就是chunk块的大小,如果数目差异较大,直接移动chunk即可,最后shard维护自己的片键范围也简单了很多。所以引入chunk的概念是一个很好的缓冲。

其次MongoDB的路由信息是基于范围的,这样在做balancing以后修改路由信息很简单,只需要修改shard的范围即可,如果采用除模等运算,还需要涉及一致性哈希等问题。基于范围和基于哈希函数或者除模运算的不同在于,范围的路由信息与插入的数据有关,不同的数据集可能会得到不同的范围集,是随着数据的插入而动态生成的。哈希函数这种有点静态的味道,只要给一个片值,不管有没有数据,不管其他数据如何,结果都是固定的。所以,基于范围可能在插入数据时需要维护路由信息,但是在修改时很容易,使用哈希法,虽然插入数据时不需要做事情,但是在动态修改拓扑结构以后,路由信息就会出问题。具体使用哪一个看场景看需求了,MongoDB要做balancing,所以肯定选择范围法更好。

标签:一个,MongoDB,chunk,shard,切分,哈希,片键
From: https://blog.51cto.com/u_15873544/5844091

相关文章

  • Python操作MongoDB
    一安装pymongopipinstallpymongo==3.4导入MongoClientfrompymongoimportMongoClient 二连接MongoDB数据库MongoDB端口号:27017连接MongoDB我们需要使用P......
  • 电影推荐系统项目实战:环境配置与搭建:Linux环境下 MongoDB的配置与安装 ----- centos7
    1.在主机中下载好Linux版本的MongoDB压缩包:连接如下:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.3.tgz 2.打开VM,启动虚拟机(这里是hadoop102)......
  • MongoDB集群之复制集,分片
    目录1集群1.1简介1.2复制集1.2.1简介1.2.2复制集设置1.2.2.1创建目录并启动1.2.2.2配置及初始化1.2.2.3操作节点1.2.2.4不正常关闭服务1.3分片1.3.1简介1.3.2......
  • Mongodb数据库和MySQL的比较
    谈谈Mongodb和MySQL的区别什么是Mongodb数据库Mongodb是一个介于关系数据库和非关系数据库之间的产品(Nosql),非关系型数据库(nosql),属于文档型数据库。文档是mongoDB......
  • Linux 下使用cut命令,实现更好切分数据
    cut是什么一个Unix终端命令切割行内容,并进行标准输出可以按照字节,字符,分隔符进行切分能有什么用我们举一个简单的例子(非全部示例)来描述cut有什么用,可以做什么简洁输出,去除干......
  • Installing MongoDB-6.0.2 on openEuler-22.09
    一、InstallingMongoDB-6.0.2onopenEuler-22.091查看版本openEuler-22.09和CentOS8.3里安装无差别,直接一步到位好吧! X、OneStepSuccesssystemctlstopfi......
  • mongodb添加删除节点及仲裁节点
    温馨提示:此mongodb版本为5.0.11,并注意,如果要删除节点,可以直接删除,添加节点前要先删除仲裁节点。rs.remove("192.168.0.180:27017");  (移除节点,如果移除仲裁节点一直卡......
  • 【详细教程】一文参透MongoDB聚合查询
    MongoDB聚合查询什么是聚合查询聚合操作主要用于处理数据并返回计算结果。聚合操作将来自多个文档的值组合在一起,按条件分组后,再进行一系列操作(如求和、平均值、最大值、最......
  • linux安装mongodb 并且远程连接
    一、引言​​MongoDB​​是一个由C++语言编写的基于分布式文件存储的数据库,MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关......
  • mongodb基本操作合集
    创建管理员账号useadmindb.createUser({user:"root",pwd:"xxxxxx",roles:[{role:"root",db:"admin"}]})其他库创建账号......