MongoDB 3.2双节点集群中所有集合为何都处于同一副本集?
嘿,这个问题我之前在测试MongoDB分片集群的时候也碰到过,结合你用的3.2版本特性,大概率是这几个原因导致的,咱们一步步拆解:
1. 小集合未触发Chunk自动迁移(最常见)
MongoDB分片集群的默认逻辑是:只有当单个Chunk大小达到阈值(默认64MB),或者分片上的Chunk数量超过配置的平衡阈值时,才会启动平衡器把Chunk迁移到其他分片。你每个集合只插入了1条文档,大小远小于64MB,所以这些集合的初始Chunk会一直留在数据库的初始分片(也就是你创建test数据库时默认分配的那个副本集分片),完全不会触发自动迁移。
验证方式
登录MongoDB的mongos节点,执行sh.status()命令,你会看到所有集合的Chunk都只挂载在同一个分片下,没有任何分裂或迁移的记录。
解决办法(测试场景专用)
如果只是为了测试分片分布效果,可以用以下两种方式强制调整:
- 手动迁移指定集合的Chunk:
// 替换成你的集合名、分片键值和目标分片名称 sh.moveChunk("test.your_collection_name", {your_shard_key: "your_key_value"}, "target_shard_name") - 临时调小Chunk大小:
调小后,哪怕小集合也可能触发Chunk分裂,平衡器会自动把分片分布到不同节点,测试完成后记得改回默认的64MB。// 把Chunk大小改成1MB(仅测试用,生产环境别这么干) db.settings.save({_id:"chunksize", value: 1})
2. 第二个副本集未被添加为分片节点
你提到集群包含2个副本集,但有可能你只把其中一个加入了分片集群的分片列表里,另一个只是作为独立副本集存在,并没有参与分片。
验证方式
执行sh.status(),查看输出里的shards部分,如果只有一个分片条目,就说明第二个副本集没被正确添加。
解决办法
把第二个副本集添加为分片:
// 替换成你的第二个副本集名称和节点地址 sh.addShard("your_second_replica_set_name/xx.xx.xx.xx:27017")
3. 分片键的选择导致哈希值集中在同一片分片
如果你用的是哈希分片键,理论上哈希能保证均匀分布,但极端情况下(比如每个集合的分片键值完全一致,或者重复度极高),哈希后的结果会落在同一个Chunk里,导致所有集合都绑定在同一个分片上。
验证方式
在mongos里用shardKeyHash()函数计算每个集合的分片键值哈希,比如:
shardKeyHash({your_shard_key: "your_value"})
如果所有集合的哈希结果都一样,那就是这个问题。
解决办法
测试场景下,可以给每个集合设置唯一且有足够基数的分片键,比如把集合名称作为分片键的一部分,保证每个集合的分片键值不重复,这样哈希后就能分散到不同分片。
4. 平衡器未开启或数据库被固定到单个分片
如果分片集群的平衡器被手动关闭了,或者你在启用test数据库分片时,强制指定了主分片且未开启自动平衡,所有新创建的集合都会默认落在这个固定分片上。
验证方式
- 检查平衡器状态:
sh.getBalancerState(),返回false说明平衡器关闭了。 - 查看数据库主分片:执行
sh.status(),在databases部分看test数据库的primary字段是不是固定为某个分片。
解决办法
- 开启平衡器:
sh.startBalancer() - 如果数据库被固定了主分片,可以通过调整平衡器配置让它重新参与分片分布(3.2版本需要确保平衡器运行一段时间,让系统自动调整)
内容的提问来源于stack exchange,提问作者MauriRamone

