//
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、执行:
代码语言:javascript复制use config
db.settings.save( { _id:"chunksize", value: <sizeInMB> } )
其中,value的单位是MB,如果要改成128M,直接value=128即可。
如何开启和关闭chunk的autosplit操作?
方法一:
使用sh.disableAutoSplit和sh.enableAutoSplit命令来关闭和打开chunk的autosplit
代码语言:javascript复制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操作:
代码语言:javascript复制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表:
代码语言:javascript复制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的速度怎么样?如果业务有写入会不会影响?
官方文档上的说明:Splits are an efficient meta-data change.也就是说,这个操作是元数据层面的一个高效的操作,按理说不会对业务的写入产生影响。
实际操作中,在4.2.14版本的MongoDB中,关闭balancer(也就意味着关闭了autosplit),导入一个包含9亿条数据的集合,这个数据集合一共只有2个chunk,每个chunk大概100多G数据。
然后开启balancer(也就意味着开启了autoplit操作),进行数据写入,整个autosplit操作在30s以内就完成了,autosplit之后,整个集合的chunk数变成了9000左右。在此期间,数据写入没有报错,所以可以判定这个autosplit的操作整体对写入没有影响。
代码语言:javascript复制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拆分具体情况,可以使用下面的命令来查看:
代码语言:javascript复制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