从分片集群中删除分片
要删除分分片,您必须确保分片的数据已迁移到集群中的其余分片。 此过程描述如何安全地迁移数据和删除分分片。
关于此任务
执行此过程时创建、分片或移动集合可能会导致中断并导致意外结果。
请勿使用此过程将整个集群迁移到新硬件。 要迁移,请参阅将自管理分片集群迁移到不同硬件。
当您从集群中删除数据段分布不均匀的分片时,负载均衡器首先从要清空的分片中删除数据段,然后均衡剩余的不均匀数据段分布。
删除分分片可能会导致打开的变更流游标关闭,并且关闭的变更流游标可能无法完全恢复。
您可以在分片删除进程中安全地重启集群。如果您在清空进程中重启集群,则在集群组件重启后,清空会自动继续。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 (和子步骤)。
返回步骤
1
,检查排干分片上是否有剩余的未分片集合。
更改主分片
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
字段包括以下字段:
字段 | 说明 |
---|---|
| 分片上当前剩余的数据段分片 |
| 主分片分片为 分片 的数据库分片。 这些数据库在 |
| 在 如果 清除 |
继续检查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 }) }