//
MongoDB 之chunk分裂之autosplit
//
在MongoDB分片集群中,使用分片键将数据分割成连续的数据块,这种数据块称之为chunk。
默认的chunk的大小是64MB,随着数据的写入,chunk的数据会越来越多,当chunk的数量超过这个默认值的时候,如果再对集合进行insert和update操作,则会触发chunk的分裂操作,也就是chunk的split操作。
这里需要注意一点,如果我们关闭了chunk的autosplit属性,那么这个chunk就不会自动分裂。当我们重新打开这个autosplit属性的时候,MongoDB并不会直接帮助我们进行autosplit,这里必须要有insert和update来触发这个split的动作。
chunk分裂的过程类似下面这样:
如图,一个64.2MB的chunk分裂成了两个32.1MB的chunk。
如何设置chunk的默认大小?
如果你不想chunk频繁的进行分裂,可以适当调大这个chunk的默认大小,但是也不能太大,否则后续每个chunk数量不均匀的时候,搬迁的时候会有压力。
按照官网的说法,默认的64MB能够满足大多数的业务需求,一般不建议改,如果确实由于业务需求,需要改动,可以使用下面的办法:
1、连接到mongos上
2、执行:
use config db.settings.save( { _id:"chunksize", value: <sizeInMB> } )
其中,value的单位是MB,如果要改成128M,直接value=128即可。
如何开启和关闭chunk的autosplit操作?
方法一:
使用sh.disableAutoSplit和sh.enableAutoSplit命令来关闭和打开chunk的autosplit
mongos> db.settings.find() { "_id" : "autosplit", "enabled" : true } mongos> sh.disableAutoSplit() WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) mongos> db.settings.find() { "_id" : "autosplit", "enabled" : false } mongos> sh.enableAutoSplit() WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) mongos> db.settings.find() { "_id" : "autosplit", "enabled" : true }
方法二:
如果你的mongodb是4.2及以上版本,可以使用balancer的开关命令来开关chunk的autosplit操作:
mongos> db.settings.find() { "_id" : "balancer", "mode" : "full", "stopped" : false } { "_id" : "autosplit", "enabled" : true } //关闭balancer mongos> sh.stopBalancer() { "ok" : 1, } mongos> db.settings.find() { "_id" : "balancer", "mode" : "off", "stopped" : true } { "_id" : "autosplit", "enabled" : false } mongos> mongos> //开启balancer mongos> sh.startBalancer() { "ok" : 1, } mongos> db.settings.find() { "_id" : "balancer", "mode" : "full", "stopped" : false } { "_id" : "autosplit", "enabled" : true }
方法三:
直接使用save命令,修改config数据库下面的settings表:
mongos> use config mongos> db.settings.find() { "_id" : "autosplit", "enabled" : true } mongos> db.settings.save({ "_id" : "autosplit", "enabled" : false }) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) mongos> db.settings.find() { "_id" : "autosplit", "enabled" : false } mongos> db.settings.save({ "_id" : "autosplit", "enabled" : true }) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) mongos> db.settings.find() { "_id" : "chunksize", "value" : 1 } { "_id" : "balancer", "mode" : "full", "stopped" : false } { "_id" : "autosplit", "enabled" : true }
chunk split的速度怎么样?如果业务有写入会不会影响?
官方文档上的说明: 也就是说,这个操作是元数据层面的一个高效的操作,按理说不会对业务的写入产生影响。
实际操作中,在4.2.14版本的MongoDB中,关闭balancer(也就意味着关闭了autosplit),导入一个包含9亿条数据的集合,这个数据集合一共只有2个chunk,每个chunk大概100多G数据。
然后开启balancer(也就意味着开启了autoplit操作),进行数据写入,整个autosplit操作在30s以内就完成了,autosplit之后,整个集合的chunk数变成了9000左右。在此期间,数据写入没有报错,所以可以判定这个autosplit的操作整体对写入没有影响。
shard key: { "number" : 1 } unique: false balancing: true chunks: test1 1 autosplit之后的结果: shard key: { "number" : 1 } unique: false balancing: true chunks: test1 9546
当然,如果你想看shard的chunk拆分具体情况,可以使用下面的命令来查看:
mongos> db.test.getShardDistribution() Shard test at test1/xxx.xxx.xxx.xx:port data : xxx MiB docs : xxxxx chunks : xxxx estimated data per chunk : xxxx MiB estimated docs per chunk : xxxxx Totals data : xxxxx MiB docs : xxxxx chunks : xxxx Shard test contains 100% data, 100% docs in cluster, avg obj size on shard : xxxxx