从分片集群中删除分片
要删除分片片,您必须确保该分片的数据已迁移到集群中的其余分片。 此过程描述如何安全地迁移数据和删除分分片。
关于此任务
执行此过程时创建、分片或移动集合可能会导致中断并导致意外结果。
请勿使用此过程将整个集群迁移到新硬件。 要迁移,请参阅将自管理分片集群迁移到不同硬件。
当您从集群中删除数据段分布不均匀的分片时,负载均衡器首先从要清空的分片中删除数据段,然后均衡剩余的不均匀数据段分布。
删除分分片可能会导致打开的变更流游标关闭,并且关闭的变更流游标可能无法完全恢复。
您可以在分片删除进程中安全地重新启动集群。 如果在正在进行的排干进程重新启动集群,则在集群组件重新启动后,排干会自动继续。 MongoDB会在
config.shards
集合中记录分分片排干。
开始之前
此过程使用
sh.moveCollection()
方法将集合从已删除的分分片移出。 在开始此过程之前,请查看moveCollection
注意事项和要求,以了解命令行为。要删除分分片,请先使用 连接到集群的
mongos
mongosh
实例之一。
步骤
确保负载均衡器已启用
要从分迁移数据,必须启用分片负载均衡器进程。 要检查负载均衡器状态,请使用sh.getBalancerState()
方法:
sh.getBalancerState()
如果操作返回true
,则负载均衡器已启用。
如果操作返回false
,请参阅启用负载均衡器。
确定要删除的分片的名称
要查找分片的分片,请运行listShards
命令:
db.adminCommand( { listShards: 1 } )
shards._id
字段包含分分片名称。
从分片中移除数据段
为分片删除的分片运行removeShard
命令:
db.adminCommand( { removeShard: "<shardName>" } )
注意
mongos
将 removeShard
命令的写关注转换为 "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
移动数据可能比等待负载均衡器迁移数据段更快。 集群确保数据不会放置在任何正在排干的分片上。 您不能同时运行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 、 Move collections off of the shard (和子步骤)。
更改主分片
db.printShardingStatus()
在命令输出的databases
部分,检查database.primary
字段。 如果primary
字段是已删除的分分片,则必须将该数据库的主节点 (primary node in the replica set)节点移动到其他分分片。
要更改数据库的主分片,请运行movePrimary
命令。
警告
运行movePrimary
时,在Move collections off of the shard步骤中未移动的任何集合在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 }) }