目录

MongoDB多个复制集到分片集群的数据同步

背景

某服务升级,计划将原来多个v2.4复制集升级为v3.0分片集群。

问题

在多个rs的增量同步过程中,发现分片集群的机器负载很高,在服务高峰时期,oplog追的慢,同步开始滞后,延迟时间有上升趋势。

整个同步过程包含两个阶段:

  • 初始同步

    • 目标是全部集合
    • insert 10w/s,大小取决于目标分片集群的性能
  • 增量同步

    • 目标是oplog
    • update 3w/s,大小取决于全部源端rs的update

分析

机器负载高,完全不符合预期,问题出在哪里?为什么初始同步没问题,增量同步会出现性能瓶颈?

从两个方面考虑:

  1. 增量同步的特殊性

    复制集中,_id保证文档的唯一性,所有对于该文档的update/delete操作,体现在oplog,均是以_id作为条件。

  2. 分片集群

    同步目标是分片集群,集合做了分片,片键(shard key)是什么?对于update/remove操作的oplog,如果片键是_id,oplog回放可以利用片键;如果片键不是_id,那么oplog回放无法利用片键。

回到问题本身,目标集合的片键非_id,对于一个update/remove操作的oplog,其回放不能直接定位到目标shard,那么该oplog将在所有shard上都执行一次,尽管这条操作仅在目标shard(包含_id指定的文档)上执行成功,但是在其他shard上会执行一次query,这里发生了不必要的性能消耗。

至于为什么insert不会有瓶颈,因为insert操作中包含文档的所有field,自然能够利用片键:)

解决方法

一般情况下,片键不会是_id,如果源端rs的update/remove的OPS高,可考虑分批导入到分片集群,比如新集群计划容纳10个rs,可以先导入5个rs,等业务切换完成,再导入其余5个rs。