背景

  • 某客户反馈某个MongoDB Sharding集群中,各个分片节点chunk分布严重不均衡,且每天晚上在迁移窗口(activeWindow)进行chunk迁移操作在日志均报错失败,需要分析原因。

影响面

  • 各分片节点数据严重倾斜,数据无法自动均衡。

环境

  • MongoDB版本: 3.4.9

  • 分片节点: 3个mongos节点,三个config server节点,后端三个分片节点,分片副本集名称分别为shard1、shard2和shard3。 

问题定位思路及流程

  • 查看sh.status()输出,因修改部分表名和集合名;

从sh.status()的输出中可以发现db01_xxx库中col01_xxxx_info和col01_xxxx_info_2019在后端各个shard的chunk数量已经严重不均衡,前者chunk数量之差47470-43068为4402个chunk,后者37053-29为37024个chunk,遇到这种情况,第一反应是看config primary的日志,MongoDB默认情况会开启balancer进程在各个shard之间迁移chunk来让shard间的chunk数量基本保持一致,chunk迁移的方向是从chunk数量最多的分片往chunk数量最少的分片迁移,在3.2版本及以下,balancer进程由Mongos发起,如果有多个Mongos进程,多个Mongos会竞争一把锁,谁获得锁谁就将获得运行balancer进程的权限,但是在3.4版本及以后,balance进程已经放在了config server的Primary节点,这样就不会有锁竞争这一过程了,查看config primary的在迁移窗口的日志有大量如下报错:

  1. 2019-05-27T00:04:06.140+0800 I SHARDING [Balancer] Balancer move db01_xxx.col01_xxxx_info_2019: [{ col01_column_1: "3177000047924787", sharedDate: new Date(1546561546000) }, { billingContractNo: "3177000049293528", sharedDate: new Date(1548383450000) }), from shard2, to shard1 failed :: caused by :: ConflictingOperationInProgress: Unable to start new migration because this shard is currently donating chunk [{ col01_column_1: "3177000525560227", sharedDate: new Date(1527215797000) }, { col01_column_1: "3177000525560227", sharedDate: new Date(1527217436000) }) for namespace db01_xxx.col01_xxxx_info to shard3

从日志得到以下信息:

1. 存储col01_xxxx_info_2019集合的chunk的迁移方向是从shard2往shard1迁移,shard2 chunk数量最多,shard1数量最少,现象符合。

2. 存储col01_xxxx_info集合的chunk的迁移方向是从shard1往shard3迁移(donating chunk),shard1数量最多,而shard3 chunk数量最少,现象符合。

3. 第1点失败的原因是第二点,原因是自动迁移的进程产生了冲突(ConflictingOperationInProgress)并等待,从而导致迁移失败。

该现象与MongoDB已知的BUG现象基本一致,该BUG表示当存在多个集合的自动的数据均衡操作时,分片节点不能同时作为源端和目标端,BUG链接为:Sharding balancer schedules multiple migrations with the same conflicting source or destination[链接1](相关链接见文末)

修复验证

  • 通过日志及相关信息可知,db01_xxx.col01_xxxx_info集合的数据较为均衡,可临时通过以下命令将该集合的自动Balancer停用,防止db01_xxx.col01_xxxx_info_2019做数据迁移时出现冲突,相关命令如下:

  1. // 禁用自动balance

  2. sh.disableBalancing("db01_xxx.col01_xxxx_info");


  3. // 启用自动balance

  4. sh.enableBalancing("db01_xxx.col01_xxxx_info");

结论

1. MongoDB balancer进程启动后,通常会在两种情况下来决定是否要做迁移使用 removeShard 后分片数量发生了变化会做自动迁移;

通过对比持有chunk最多和最少的shard, 集合的chunk数量在各个后端shard之间的数量达到一定的差值时会触发自动迁移,迁移阈值[链接2](相关链接见文末)如下:

集合chunk数量迁移阈值
<202
<804
>=808

2. 该BUG在MongoDB 3.4.11版本以下会触发,3.4.11及以上版本,3.6版本均已修复,因此要想解决此问题需要将集群升级到3.4.11版本以上。

相关链接

  • [链接1] https://jira.mongodb.org/browse/SERVER-29423

  • [链接2] https://docs.mongodb.com/manual/core/sharding-balancer-administration/#migration-thresholds 

近期社区动态