要删除分片片,您必须确保该分片的数据已迁移到集群中的其余分片。 此过程描述如何安全地迁移数据和删除分分片。
关于此任务
执行此过程时创建、分片或移动集合可能会导致中断并导致意外结果。
请勿使用此过程将整个集群迁移到新硬件。 要迁移,请参阅将自管理分片集群迁移到不同硬件。
当您从集群中删除数据段分布不均匀的分片时,负载均衡器首先从要清空的分片中删除数据段,然后均衡剩余的不均匀数据段分布。
删除分分片可能会导致打开的变更流游标关闭,并且关闭的变更流游标可能无法完全恢复。
您可以在分片删除进程中安全地重新启动集群。 如果在正在进行的排干进程重新启动集群,则在集群组件重新启动后,排干会自动继续。 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 call moveCollection for collectionsToMove and afterwards movePrimary for the dbsToMove", "dbsToMove" : [ "db1", "db2" ], collectionsToMove: ["db1.collA"] "ok" : 1, "operationTime" : Timestamp(1575398919, 2), "$clusterTime" : { "clusterTime" : Timestamp(1575398919, 2), "signature" : { "hash" : BinData(0,"Oi68poWCFCA7b9kyhIcg+TzaGiA="), "keyId" : Long("6766255701040824328") } }
分分片进入draining
状态,负载均衡器开始将数据段从已删除的分片分片到集群中的其他分片。 这些迁移缓慢进行,以避免对整个集群造成严重影响。 根据网络容量和数据量,此操作可能需要几分钟到几天才能完成。
提示
当分片处于draining
状态时,您可以使用分片命令重新分发已删除分片片的数据。
使用reshardCollection
移动数据可能比等待负载均衡器迁移数据段更快。 集群确保数据不会放置在任何正在排干的分片上。 您不能同时运行moveCollection
和reshardCollection
操作。
有关完整过程,请参阅为添加和删除分片而重新分片。
将未分片的集合移动到另一个分片
确定需要移动哪些集合
要列出分片上的未分片集合,请使用聚合阶段
$listClusterCatalog
:use admin db.aggregate([ { $listClusterCatalog: { shards: true } }, { $match: { $and: [ { sharded: false }, { shards: '<shard_to_remove>' }, { type: { $nin: ["timeseries","view"] } }, { ns: { $not: { $regex: "^enxcol_\..*(\.esc|\.ecc|\.ecoc|\.ecoc\.compact)$" }}}, { $or: [{ns: {$not: { $regex: "\.system\." }}}, {ns: {$regex: "\.system\.buckets\."}}]}, { db: { $ne: 'config' } }, { db: { $ne: 'admin' } } ]}}, { $project: { _id: 0, ns: { $cond: [ "$options.timeseries", { $replaceAll: { input: "$ns", find: ".system.buckets", replacement: "" } }, "$ns" ] } }} ]) 逐个移动集合
要移动集合,运行
sh.moveCollection()
:sh.moveCollection( "<database>.<collection>", "<ID of recipient shard>" ) 注意
moveCollection
如果在分片命名空间上运行该命令,则会分片的。 如果收到此错误消息,请忽略并返回到步骤1
以进行下一个集合。返回步骤
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 }) }