reshardcollection失败后集群仍可读写但路由不一致,部分chunk按新键路由、部分按旧键,mongos缓存失效导致查询报错;须手动清理config.reshardingoperations中非success状态文档、重置collections元数据并刷新各mongos路由配置。

reshardCollection 执行中途失败后,集群状态会怎样
reshardCollection 失败不会自动回滚已迁移的 chunk,也不会让集合进入不可用状态——但元数据会处于不一致态:部分 chunk 已按新分片键路由,部分仍按旧键;mongos 路由表缓存可能失效,导致查询返回 Cannot target a shard key that is not present in the query 或随机 ShardKeyNotFound 错误。
关键判断:失败后集合仍可读写,但行为不可预测。不能直接重试 reshardCollection,也不能删重建——必须先清理残留状态。
如何安全终止并清理失败的 resharding 任务
失败的 resharding 会在配置服务器上留下未完成的 resharding 状态文档,阻塞后续操作。必须手动清除:
- 连接到任意
mongos,运行db.adminCommand({ listResharding: 1 })查看是否仍有活跃任务(返回非空数组即表示残留) - 若存在,需通过
config数据库直接清理:use config<br>db.reshardingOperations.deleteMany({ "state": { "$ne": "success" } })<br>db.collections.updateOne({ "_id": "mydb.mycollection" }, { $unset: { "lastModEpoch": "", "lastModTime": "" } }) - 强制刷新
mongos缓存:对每个mongos实例执行db.runCommand({ flushRouterConfig: 1 }) - 检查
sh.status()输出中该集合的 chunk 分布是否回归到原始分片键范围;若仍有跨分片键的 chunk,需人工moveChunk回原位置(仅限低峰期且确认无写入时)
重试前必须验证的三项硬性条件
重试 reshardCollection 前,以下三点任一不满足都会再次失败:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 目标分片键字段在所有文档中必须存在且类型一致(
find({ "newKey": { $exists: false } }).count()必须为 0) - 新分片键索引必须已建好且为
background: true(否则建索引过程会卡住 resharding) - 所有分片的磁盘空闲空间 ≥ 1.2 × 当前集合
storageSize(db.mycollection.stats().storageSize),注意是每个分片单独计算,不是总和
forceRedistribution: true 的副作用与规避方式
加 forceRedistribution: true 会让 MongoDB 忽略当前 chunk 分布,强制全量重分布——但它会触发所有分片同时重建 chunk,极大放大 I/O 和锁竞争。实际中多数失败都源于此参数滥用。
更稳妥的做法:
- 去掉
forceRedistribution,让 MongoDB 基于现有 chunk 边界逐步迁移(默认行为) - 若必须重分布,改用
numInitialChunks: 180(而非默认 90)来减少单次迁移 chunk 数量,降低单次锁时长 - 配合
maxTimeMS控制单次命令超时(如{ maxTimeMS: 300000 }),避免长时间卡死
真正难处理的不是失败本身,而是残留的 reshardingOperations 文档和未刷新的 mongos 路由缓存——这两处漏掉,重试永远在原地打转。










