分片集群故障演练必须围绕真实故障路径设计,只动可恢复组件、避开元数据层硬伤,每次操作后须验证应用行为;mongos重启需关注客户端连接池与超时配置,shard降级要控制范围并确认无活跃迁移,config server网络隔离前须禁用均衡器,恢复后需手动刷新会话缓存,应用须能处理部分分片不可用场景。

分片集群故障演练不是“模拟宕机就行”,而是必须围绕真实故障路径设计动作,否则测了也白测。核心原则是:只动可恢复的组件,避开元数据层硬伤,且每次操作后必须验证应用行为是否符合预期。
mongos 实例逐个重启时应用连接是否中断
这是最常被误判的环节。mongos 本身无状态,但客户端 SDK 的连接池和重试策略会直接影响感知结果。
- 应用侧需配置
connectTimeoutMS和socketTimeoutMS(建议 ≥ 30000),否则短时不可用会被直接抛SocketException - 不要只 kill -9
mongos进程,要配合netstat -tuln | grep :27017确认端口释放干净,避免 TIME_WAIT 占用导致新实例启动失败 - 验证重点不是 mongos 能否起来,而是应用发一条
db.collection.find({}).limit(1)是否在 5 秒内返回——这比看日志更反映真实链路
故意让一个 shard 副本集降级为单节点
这是检验写一致性与自动故障转移的关键动作,但必须控制范围:只对非主分片(如 shard02)操作,且确保该 shard 当前无活跃 chunk 迁移任务。
- 先执行
sh.status()确认目标 shard 的 chunk 分布均衡,再查rs.conf()获取当前 primary 成员 host - 在非 primary 节点上执行
db.shutdownServer(),观察rs.status().members中 stateStr 是否变为SECONDARY或REMOVED,而非卡在STARTUP2 - 立刻跑
db.runCommand({getShardVersion: 1}),若返回"ok" : 1且无"errmsg",说明 mongos 已完成配置刷新;若报"Failed to refresh shard version",说明 config server 同步延迟过高,需查config.mongos集合更新时间戳
人为断开 config server 副本集的 majority 网络
这是高危动作,仅限测试环境且必须提前禁用 chunk 自动平衡(sh.setBalancerState(false)),否则可能触发元数据写阻塞。
- 用 iptables 在 config server 成员间封禁 27019 端口(默认 config server 端口),例如:
iptables -A INPUT -p tcp --dport 27019 -j DROP - 等待 30 秒后执行
rs.status(),确认是否出现"stateStr" : "PRIMARY"成员数 ≤ 1;此时sh.status()应仍可读,但sh.splitAt()会立即报错"cannot acquire lock" - 恢复网络后,必须手动触发
db.adminCommand({refreshLogicalSessionCacheNow: 1}),否则部分 session 可能卡在旧配置中长达 30 分钟
验证应用能否处理 partial availability
真正难的是业务代码——当某个 shard 全挂而其他 shard 正常时,应用是否静默丢数据、是否重试逻辑失控、聚合查询是否崩掉。
- 构造跨分片查询:
db.orders.aggregate([{$match: {status: "pending"}}, {$group: {_id: "$region", count: {$sum: 1}}}]),然后 kill 掉承载region: "us-east"数据的 shard - 观察返回结果:MongoDB 默认返回已成功响应的 shard 结果 + 报错信息(
"$err": "Could not target ..."),应用层必须捕获MongoCursorNotFoundException或ExecutionTimeoutException并降级处理 - 切勿依赖驱动自动重试——Java Driver 4.x 默认对 aggregate 不重试,Go Driver 的
RetryReads也不覆盖分片不可达场景
最容易被忽略的是 config server 的 oplog 大小:如果演练中频繁触发 chunk 拆分又回滚,小 oplog 会导致 secondary 同步滞后,后续故障时无法快速接管 primary。生产环境 config server 的 wiredTiger.engineConfig.cacheSizeGB 应 ≥ 4,oplog 容量不低于 72 小时写入量。

















