从分片集群中移除分片
要移除一个分片,您必须确保分片的数据已迁移到集群中剩余的分片。本程序描述了如何安全地迁移数据并移除分片。
关于此任务
在执行此程序时创建、分片或移动集合可能会造成中断,并导致意外结果。
不要使用此程序将整个集群迁移到新硬件。要迁移,请参阅将自管理分片集群迁移到不同硬件。
当您从具有不均匀数据块分布的集群中移除分片时,均衡器首先从正在排空的分片中移除数据块,然后平衡剩余的不均匀数据块分布。
移除分片可能会使打开的更改流游标关闭,关闭的更改流游标可能无法完全恢复。
您可以在移除分片的过程中安全地重启集群。如果在进行排空过程中重启集群,集群组件重启后自动继续排空。MongoDB在
config.shards
集合中记录分片排空状态。
开始之前
此过程使用
sh.moveCollection()
方法将集合从已删除的分区移动出去。在开始此过程之前,请查看moveCollection
的 注意事项 和 要求,以了解命令的行为。要删除分区,首先使用
mongosh
.
步骤
确保均衡器已启用
要从分区迁移数据,必须启用 均衡器 进程。要检查均衡器状态,使用 sh.getBalancerState()
方法
sh.getBalancerState()
如果操作返回 true
,则均衡器已启用。
如果操作返回 false
,请参阅 启用均衡器。
确定要删除的分片名称
要找到分片名称,运行 listShards
命令
db.adminCommand( { listShards: 1 } )
shards._id
字段包含分片名称。
从分片中删除数据块
运行要删除的分片的 removeShard
命令
db.adminCommand( { removeShard: "<shardName>" } )
注意
mongos
将 写关注 转换为 "majority"
。
removeShard
操作返回
{ "msg" : "draining started successfully", "state" : "started", "shard" : "<shardName>", "note" : "you need to drop or movePrimary these databases", "dbsToMove" : [ "db1", "db2" ], "ok" : 1, "operationTime" : Timestamp(1575398919, 2), "$clusterTime" : { "clusterTime" : Timestamp(1575398919, 2), "signature" : { "hash" : BinData(0,"Oi68poWCFCA7b9kyhIcg+TzaGiA="), "keyId" : NumberLong("6766255701040824328") } } }
分片进入 draining
状态,均衡器开始将数据块从被删除的分片迁移到集群中的其他分片。这些迁移是缓慢进行的,以避免对集群的整体影响造成严重冲击。根据您的网络容量和数据的量,此操作可能需要几分钟到几天才能完成。
提示
当分片处于 draining
状态时,您可以使用 reshardCollection 命令来重新分配从被删除的分片上的数据。
使用 reshardCollection
移动数据可能比等待均衡器迁移数据块要快。集群确保数据不会放置在任何正在排空的分片上。您不能同时运行 moveCollection
和 reshardCollection
操作。
列出分片集合命名空间
要返回分片集合命名空间列表,使用 $shardedDataDistribution
阶段并投影 ns
字段
use admin db.aggregate( [ { $shardedDataDistribution: { } }, { $project: { ns: 1 } } ] )
将输出记录下来,以便在本教程的后续部分参考。
将集合从分片上移除
对于集群中的每个数据库(除admin和config外),执行以下步骤
列出数据库集合
列出数据库中的集合,排除以下类型的集合
支持CSFLE的内部集合
系统集合
时间序列集合
视图
use <databaseName> db.getCollectionInfos( { $and: [ { type: { $nin: [ "view", "timeseries" ] } }, { name: { $not: { $regex: "^system\." } } }, { name: { $not: { $regex: "^enxcol_\..*(\.esc|\.ecc|\.ecoc|\.ecoc\.compact)$" } } } ] }, { nameOnly: true } ) 移动必要的集合
对由
getCollectionInfos()
返回的每个集合执行以下步骤。注意
一次只能有一个
moveCollection
操作可以执行。在移动到下一个集合之前完成所有子步骤。确定集合是否需要迁移。
运行
$collStats
聚合阶段,并投影ns
和shard
字段db.<collName>.aggregate( [ { $collStats: { } }, { $project: { ns: 1, shard: 1 } } ] ) 如果满足以下任何一项标准,则跳过集合并返回到步骤
i
,以处理数据库中的下一个集合ns
字段存在于步骤 4 的$shardedDataDistribution
输出中。shard
字段不是要移除的分片。
如果上述任何一项标准都不满足,则继续执行当前集合的步骤
ii
。迁移集合。
要迁移集合,请在集合上运行
sh.moveCollection()
sh.moveCollection( "<namespace>.<collection>", "<ID of recipient shard>" ) 注意
如果你在分片命名空间上运行命令,则
moveCollection
将失败。如果你收到此错误消息,请忽略它并返回到步骤i
,以处理数据库中的下一个集合。为数据库中的每个集合返回到步骤
i
。
对其他数据库重复此过程
重复步骤 6将集合从分片上移除(以及子步骤)以处理集群中每个数据库。
更改主分片
运行 db.printShardingStatus()
方法
db.printShardingStatus()
在命令输出的 databases
部分中,检查 database.primary
字段。如果 primary
字段是已移除的分片,则必须将该数据库的主分片移动到不同的分片。
要更改数据库的主分片,请运行 movePrimary
命令。
警告
在运行 movePrimary
时,在 将集合从分片上移除 步骤中未移动的任何集合在 movePrimary
过程中将不可用。
db.adminCommand( { movePrimary: <dbName>, to: <shardName> } )
检查迁移状态
要检查迁移进度,请再次从 admin
数据库运行 removeShard
db.adminCommand( { removeShard: "<shardName>" } )
输出中,remaining
字段包含以下字段
字段 | 描述 |
---|---|
chunks | 当前在分片上剩余的块数量 |
dbs | 其 主分片 是该分片的数据库数量。这些数据库在 dbsToMove 输出字段中指定。 |
jumboChunks | 在所有块中,是 大块 的块数量。 如果 清除大块标志后,均衡器可以迁移这些块。有关迁移过程的详细信息,请参阅 范围迁移过程。 |
继续检查 removeShard
命令的状态,直到剩余块的数量为 0。
db.adminCommand( { removeShard: "<shardName>" } )
完成分片删除
要完成分片删除过程,请重新运行 removeShard
命令
db.adminCommand( { removeShard: <shardName> } )
如果移除了分片,命令输出类似于以下内容
{ msg: 'removeshard completed successfully', state: 'completed', shard: '<shardName>', ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1721941519, i: 7 }), signature: { hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0), keyId: Long('0') } }, operationTime: Timestamp({ t: 1721941519, i: 7 }) }