mongodb 分片块迁移 500GB 需要 13 天 - 这是慢还是正常?

ren*_*ior 9 mongodb sharding

我有 mongodb 分片集群,分片键是散列的。它有 2 个分片副本集。每个副本集有 2 台机器。

我通过添加另外 2 个分片副本集做了一个实验,它开始重新平衡。

然而,一段时间后我发现块迁移相当缓慢。移动 1.4GB 数据需要 1 小时。

这让我很担心,这意味着我必须等待 13 天才能完成 500GB 的块迁移!

我是这个东西的新手,无论是慢速、快速还是正常,我都没有上帝的感觉。但是,这些数字仍然不能说服我。

关于实验的附加说明: - 使用 m3 中型 aws 机器 - 没有其他进程在运行,只有块迁移 - 默认的 mongodb 分片安装,无需进一步配置 - shardkey 在对象 id (_id) 处使用散列 - 最大块大小 64MB

Ada*_*m C 11

更新:2018 年 4 月

这个答案在提出问题时是正确的,但从那时起事情就发生了变化。自从3.4版本引入了parallelism,我原先引用的ticket也被关闭了。有关更多信息,我在这个最近的答案中介绍了一些细节。我将保留答案的其余部分,因为它仍然是一般问题/约束的良好参考,并且对旧版本的任何人都有效。

原答案

如果您有兴趣,我会在M202 高级课程中完整解释块迁移会发生什么。一般而言,我们只是说迁移不是很快,即使对于空块,因为正在执行内务处理以确保迁移在活动系统中工作(即使除了平衡之外什么都没有发生,这些仍然会发生)。

此外,整个集群一次只发生一次迁移——没有并行性。因此,尽管您有两个“完整”节点和两个“空”节点,但在任何给定时间最多只发生一次迁移(在块最多的分片和最少的分片之间)。因此,添加 2 个分片在平衡速度方面没有任何好处,只会增加必须移动的块数。

对于迁移本身,块的大小可能约为 30MiB(取决于您填充数据的方式,但通常这将是默认最大块大小的平均值)。您可以运行其中db.collection.getShardDistribution()的一些信息,并在此处查看我的答案以获取有关您的块的更多信息的方法。

由于没有其他活动正在进行,要进行迁移,目标分片(新添加的分片之一)将需要从源分片(原始 2 个分片之一)读取约 30MiB 的数据并将配置服务器更新为完成后反映新的块位置。对于没有负载的普通系统来说,移动 30MiB 的数据应该不是什么大瓶颈。

如果速度很慢,可能有多种原因,但对于不忙的系统来说,最常见的原因是:

  • Source Disk I/O - 如果数据在读取时不在活动内存中,则必须从磁盘调入
  • 网络 - 如果存在延迟、速率限制、数据包丢失等,那么读取可能需要很长时间
  • 目标磁盘 I/O - 数据和索引必须写入磁盘,大量索引会使情况变得更糟,但通常这在轻负载系统上不是问题
  • 导致中止和迁移失败的迁移问题(配置服务器问题,主数据库删除问题)
  • 复制滞后 - 用于迁移到副本集、写关注w:2w:majority默认使用并且需要最新的辅助节点来满足它。

如果系统很忙,那么内存争用、锁争用通常也是这里的嫌疑人。

要获取有关迁移需要多长时间的更多信息,如果迁移失败等,请查看您的config.changelog:

// connect to mongos
use config
db.changelog.find()
Run Code Online (Sandbox Code Playgroud)

正如您所见,并且正如我在进行培训/教育时通常告诉人们的那样,如果您知道需要 4 个分片,那么通常最好从 4 个分片开始而不是逐渐增加。如果你这样做了,那么你需要意识到添加分片可能需要很长时间,并且最初是对资源的净负面影响而不是收益(请参阅我的分片陷阱系列的第二部分,以获得更详细的讨论)。

最后,要跟踪/投票/评论功能请求以提高块迁移的并行性,请查看SERVER-4355