如何强制MongoDB刷新mongos的路由表缓存 flushRouterConfig命令与应用场景深度解析|Duuu笔记
flushRouterConfig 是唯一能强制 mongos 立即重载全部路由表的命令,需在每次分片增删、chunk 变更或 config server 异动后手动执行,否则路由错误导致查不到数据或写入失败。
mongos 路由表不更新?
flushRouterConfig
是唯一能立刻生效的命令
当分片集群新增或删除分片、修改 chunk 分布(比如手动迁移、split 或 merge)、或者 config server 配置变更后,
mongos
不会自动同步最新路由信息——它依赖缓存,且默认刷新间隔长(通常 30 秒以上),甚至可能卡住。此时查询会路由到错误分片,返回空结果或
NamespaceNotFound
,写入可能失败或写错地方。
flushRouterConfig
是唯一能强制它立即重载全部路由表的命令,不是“建议”,是必要操作。
常见错误现象:
sh.status()
显示 chunk 已迁移完成,但应用查不到数据;刚添加分片后
sh.addShard()
返回成功,但
db.collection.find()
报
ShardNotFound
;config server 重启后 mongos 仍用旧配置。
必须在
mongos
实例上执行,不能连 config server 或 shard 执行
命令格式极简:
db.runCommand({flushRouterConfig: 1})
,无参数、无返回值(成功时返回
{"ok": 1}
)
影响范围是当前连接的这个
mongos
进程,不是整个集群;多个 mongos 需各自调用
执行期间该 mongos 短暂阻塞新请求(毫秒级),但不会中断已有连接
哪些操作后必须手动刷?不是所有变更都触发自动刷新
自动刷新只响应部分 config server 的元数据变更事件,很多运维动作它根本收不到通知,尤其涉及底层状态不一致时。别信“等一会儿就好”。
执行过
sh.addShard()
或
sh.removeShard()
后——即使命令返回成功,mongos 缓存仍指向旧分片列表
手动调用
sh.splitAt()
、
sh.moveChunk()
或直接写 config 数据库改
chunks
集合后——自动刷新常延迟或失效
config server 发生主从切换、重启,或网络短暂中断恢复后——mongos 可能维持断连前的旧视图
升级 MongoDB 版本后首次启动 mongos——某些版本(如 4.2→4.4)会沿用旧缓存,导致路由混乱
flushRouterConfig
和
invalidateShardMetadata
别混用
后者是针对单个数据库/集合的元数据失效命令,作用域窄、开销小,但无法解决分片拓扑变更问题。它只清本地缓存的 collection-level 分片键、chunk 范围等,不碰分片列表、zone 配置、config server 地址这些全局路由信息。
白瓜AI
白瓜AI,一个免费图文AI创作工具,支持 AI 仿写,图文生成,敏感词检测,图片去水印等等。
下载
用
invalidateShardMetadata
的场景:某个集合的 chunk 分布被绕过 sharding 命令直接修改(如误删 config.chunks 文档),且只想让 mongos 忘掉这个集合的路由
用
flushRouterConfig
的场景:任何影响
mongos
对“哪个分片管哪段 key”的整体判断的操作
两者不互斥,但顺序重要:先
flushRouterConfig
拉全量路由,再按需
invalidateShardMetadata
清局部——反过来没用
注意:
invalidateShardMetadata
在 5.0+ 已废弃,替代方案是
refreshCollection
,但依然不解决路由表问题
生产环境调用前必须确认的三件事
这命令本身安全,但时机不对会放大问题。别在流量高峰或 config server 不稳定时乱刷。
确认目标
mongos
连接的是健康的 config server 主节点(查
db.isMaster()
输出里的
primary
字段)
检查 config server 的
config.version
和
config.shards
是否已同步完成(对比各 config server 上
db.version.findOne()
和
db.shards.find()
)
如果是滚动更新多个 mongos,避免所有实例同一秒刷——用秒级错峰(如 sleep 0.5s),否则瞬时大量 config 查询可能压垮 config server
最容易被忽略的是:刷完之后不验证。执行完立刻跑一句
sh.status()
或
db.getSiblingDB("config").chunks.findOne({ns: "db.coll"})
,确认输出和 config server 一致。缓存刷了,但 config 本身没更新,那还是白忙。
