config.chunks 是性能瓶颈,因其存储所有 chunk 元数据,高频路由查询、均衡器校验、sh.status() 全量扫描及 chunk 拆分/合并均反复读写该集合,且 MongoDB 6.0 不支持只读副本分离,所有请求打向主 config server。

Config Server 负载高,本质不是 CPU 或磁盘瓶颈,而是元数据加载和变更频繁导致的锁竞争与查询压力——尤其 config.chunks 集合被高频扫描或更新时,mongos 和均衡器都会卡住。直接压低负载,得从“少读、少写、少扫”三路下手。
为什么 config.chunks 是性能瓶颈?
config.chunks 存储所有 chunk 的范围、归属分片、版本号,10 万 chunk 就有 40–60MB BSON 数据。它被以下操作反复扫描:
-
mongos路由查询前查 chunk 分布(尤其是广播查询) - 均衡器迁移 chunk 前要读取并校验 chunk 版本
-
sh.status()、sh.printShardingStatus()等命令全量遍历该集合 - 每次 chunk 拆分/合并都触发
config.chunks写入 + 索引更新
它的 B-tree 索引无法跳过范围扫描,且 MongoDB 6.0 不支持对该集合做只读副本分离——所有读都打到主 config server。
减少 config.chunks 文档数量的实际操作
Chunk 数量直接决定 config.chunks 大小和扫描耗时。目标不是“不拆分”,而是避免碎片化:
- 用
sh.status()检查是否有大量 size: 2.1MB),它们通常是写入倾斜或删除后未合并残留 - 对相邻小 chunk 主动合并:
sh.mergeChunks("db.coll", {shardKey: min}, {shardKey: max}),注意必须是连续范围且同属一个分片 - 禁用不再使用的数据库:
sh.disableSharding("old_db"),否则其config.collections和关联的config.chunks条目仍保留在元数据中 - 避免在低基数字段上分片(如
{status: 1}),否则极易产生数百个极小 chunk
限制均衡器对 config server 的轮询压力
默认均衡器每 10 秒检查一次迁移任务,每次都要读 config.chunks + config.migrationJobs + config.locks。高频轮询会放大锁争用:
- 把均衡窗口缩窄:
db.getSiblingDB("config").settings.update({_id:"balancer"}, {$set: {activeWindow: {start:"02:00", stop:"04:00"}}}, {upsert:true}) - 关闭非必要时段的自动均衡:
sh.stopBalancer(),人工控制迁移节奏 - 调大
chunkSize(如设为128)降低拆分频率,间接减少config.chunks变更次数 - 监控
config.changelog,若发现单次迁移耗时 > 1s/GB,说明网络或磁盘已成瓶颈,此时强行开启均衡器只会拖垮 config server
真正难处理的不是配置项,而是那些“看起来正常却持续写入元数据”的行为:比如应用层高频执行 sh.splitAt()、误用 _id 作分片键导致新数据全挤进最后一个 chunk、或者没关掉旧业务的定时分片脚本。这些不会报错,但会让 config.chunks 在几周内膨胀数倍——等你注意到 mongos 响应变慢时,往往已经积压了上万无效 chunk。

















