单个Shard磁盘满是分片集群最危险的“假均衡”,因数据看似均匀分布,但shard key不当、写入倾斜或balancer未开启/卡住时,易出现“其他Shard仅30%、某Shard已98%”,导致整个集群写入阻塞,mongos返回NotMasterNoSlaveOk或直接拒绝写入。

为什么单个Shard磁盘满是分片集群最危险的“假均衡”
分片集群看似数据均匀分布,但shard key选择不当、写入倾斜或balancer未开启/卡住时,很容易出现“其他Shard才用30%,某个Shard已98%”——此时整个集群写入会阻塞,mongos返回NotMasterNoSlaveOk或直接拒绝写入。这不是负载问题,是存储瓶颈提前爆发。
如何配置有效的磁盘空间预警(不依赖云平台)
云厂商控制台的“磁盘使用率告警”通常只监控挂载点,而MongoDB的/var/lib/mongodb可能只是其中一部分;更关键的是,WiredTiger引擎的缓存膨胀、日志堆积、碎片率高,会让df -h显示还有20%空间,但db.stats()里storageSize远超dataSize,实际已无有效写入空间。
- 在每个
mongod节点上部署轻量级检查脚本,每5分钟执行:df -h /var/lib/mongodb | awk 'NR==2 {print $5}' | sed 's/%//',超过85%就触发告警 - 进
mongoshell定期查:db.serverStatus().metrics.repl.buffer.count(缓冲区积压)、db.serverStatus().storageEngine.wiredTiger.cache.trackedDirtyBytes(脏页大小),这两项突增往往是磁盘即将撑爆的前兆 - 禁用系统级
tmpfs或/dev/shm自动挂载,避免WiredTiger误用共享内存导致cache.used虚高
启用Balancer前必须验证的三个条件
balancer不是开开关就能自动均摊数据,它依赖底层元数据一致性和Chunk可迁移性。盲目开启反而会导致迁移风暴、锁表、甚至主从同步中断。
- 确认所有
config server节点状态正常:sh.status()中configServerStatus字段不能为DOWN - 检查
sh.status()输出里的balancer行是否显示Currently enabled: true,且Locks下无长期持有的balancer锁 - 确保目标Shard有足够空闲空间:若某Shard当前
storageSize为480GB,迁移目标Shard剩余空间必须>500GB(预留20GB缓冲+迁移过程临时文件)
预分片和Chunk大小设置对迁移效率的实际影响
没预分片的集合,初始只有一个Chunk,所有写入都打到同一个Shard;等数据涨到默认64MB再分裂,此时balancer要搬运大量历史数据,IO压力巨大。而过小的Chunk(如1MB)又会导致元数据爆炸、路由查询变慢。
- 新集合务必预分片:
sh.shardCollection("db.coll", {"_id": "hashed"})+sh.splitAt("db.coll", {"_id": NumberLong("...")}),按预估总量分出至少3×Shard数个初始Chunk - 生产环境建议Chunk大小设为
128MB(mongos配置项chunkSize),比默认64MB更抗突发写入,也避免频繁分裂 - 对已有大集合补救:先
sh.disableBalancing("db.coll"),再sh.splitAt()手工切分,最后sh.enableBalancing("db.coll"),别让balancer自己猜怎么切
balancerStart/balancerStop)必须避开业务高峰,且每次迁移后要人工核对sh.status()里各Shard的chunks数量和size是否收敛——它不会告诉你迁移失败,只会静默跳过不可达Shard。


















