MongoDB如何处理Jumbo块
2022-04-18 22:45 abce 阅读(248) 评论(0) 编辑 收藏 举报你是一名MongoDB DBA,当天的第一项任务是从集群中删除一个分片。听起来很吓人,但你知道这很容易。 你可以用一个简单的命令来做到这一点:
db.runCommand( { removeShard: "server1_set6" } )
mongodb会找到对应的块和数据库,并在所有的其它节点上重新平衡。你可以放心地睡了。
第二天醒来,你检查某个分片的状态,你会发现进程被夯住了:
"msg" : "draining ongoing",
"state" : "ongoing",
"remaining" : {
"chunks" : NumberLong(3),
"dbs" : NumberLong(0)
由于某种原因,有三个块没有被迁移。所以,removeShard命令夯了。接下来你会怎么做呢?
找出哪些块不能被移动
连接到mongos并检查:
mongos> use config
switched to db config
mongos> db.chunks.find({shard:"server1_set6"})
结果会显示有三个块,以及最小和最大的_id键,属于的命名空间。
最后一部分才是你需要检查的:
{
[...]
"min" : {
"_id" : "17zx3j9i60180"
},
"max" : {
"_id" : "30td24p9sx9j0"
},
"shard" : "server1_set6",
"jumbo" : true
}
块被标记为jumbo,我们必须找出为什么平衡进程为什么没有成功。
如何处理Jumbo块
所谓“jumbo chunk”,就是一个chunk的大小超过了设置的chunk的最大值。默认是64MB。当超出这个值的时候,balancer进程就不会起作用。
这只是概念上的解释,实现上就是当splitCommand发现无法将一定范围内的documents分裂到比设定值小的segment中,就会将该块标记为Jumbo。
如何清除Jumbo标记
从mongodb 4.0.15开始,可以使用clearJumboFlags命令。
在老的版本中,需要手动移除
db.getSiblingDB("config").chunks.update(
{"ns": <your_sharded_user_db.coll>, "jumbo": true},
{$unset: { "jumbo": "" }}
);
使用Indivisible处理
从mongodb4.4开始,可以使用refineCollectionShardKey命令给分片键增加一列,作为前缀。比如将 {“surname”: 1,“given_name”: 1} 修改成{“surname”: 1, “given_name”: 1, “date_of_birth”: 1}
如果版本低于或等于4.2,块大小超出设置后不能被移动。
在上面段落中描述的 can't-drain 问题场景中,你必须执行以下操作之一才能完成分片的清理,以便你可以运行最终的removeShard
1.在增加块大小设置后移动jumbo块
·遍历所有jumbo块,使用 dataSize 命令找出最大的大小。·将块大小设置更改为大于该值。·清除巨型标志(参见上面的小节)·再次开始清理,等待它移动大块。 如果想它们尽快发生,请使用 sh.moveChunk() 命令。·之后不要忘记更改块大小。
2.间或删除数据。然后重新插入数据
·仍然需要清理jumbo标记
jumbo 标志一旦被附加,即使文档被删除或以其他方式缩小,也不会自动删除,因此块在(默认)64MB 大小内。你可以手动清除巨型标志(请参阅上面的小节)并重试。
理论上,不需要手动进行任何拆分,但如果想快点确认可以将块拆分成足够小的大小,请参阅如何使用 sh.splitAt() 命令文档。