MongoDB中的大块我最近遇到了一个有趣的MongoDB集群平衡过程中的性能问题。通过对日志的深入研究,我们发现这个问题与块移动花费了很长时间有关。

正如我们所知,默认的最大块大小是64 MB。因此,这些迁移应该在目前使用的大多数硬件中非常快。

在这种情况下,有几个远远超过限制的块被移动。这是怎么发生的?这些块不应该被标记为Jumbo吗?

回顾一下大块移动

首先,让我们回顾一下我们对块移动的了解。

如果一个块中的文档数大于配置的块大小(默认64mb)除以平均文档大小的1.3倍,MongoDB不会移动该块。

如果我们有一个平均文档大小为2 KB的集合,那么超过42597(65535 / 2 * 1.3)个文档的块将无法平衡。对于文档大小不统一的集合来说,这可能是一个问题,因为在这种情况下估计不是很好。

此外,如果一个块超过了最大大小,它将被标记为Jumbo。这意味着平衡器不会试图移动它。您可以查看下面的文章了解更多关于处理大块

最后,我们必须记住块是移动的在进程的某个部分使用元数据锁因此,在块移动结束时,写操作会暂时阻塞。

在行动中的autoSplitter

在MongoDB 4.2之前,autoSplitter进程负责确保在mongos路由器上运行的块不超过最大大小。路由器进程保存有关其执行的操作的一些统计信息。参考这些统计数据来做出块分割决策。

问题是,在生产环境中,通常部署了许多这样的流程。单个mongos路由器只能部分了解特定数据块的情况。

如果多个mongos路由器更改同一块上的数据,它可能会超过最大大小,但仍然不被注意。

有许多与此主题相关的报告问题(例如,请参阅服务器- 44088服务器- 13806,服务器- 16715).

频繁重启mongos进程也可能导致同样的问题。这将导致用于进行块分割决策的统计信息被重置。

由于这些问题,autoSplitter进程被更改为在每个分片副本集的主成员上运行。这发生在MongoDB 4.2版本中(参见服务器- 9287了解更多详情)。

进程现在应该更好地防止大块,因为每个分片都有一个更准确的视图,它包含什么数据(以及它是如何被改变的)。

在这种情况下,MongoDB的版本是3.6,而autoSplitter并没有像预期的那样好。

在MongoDB中查找未检测到的大块

对于初学者,我遇到了一个脚本来打印块统计信息的摘要在这里。我们可以在此基础上进行构建,以显示有关Jumbo块的信息,并生成手动分割超过最大大小的块所需的命令。

该脚本必须从mongos路由器调用,如下所示:

并且它将打印任何执行块分割所需的命令:

您可以看到脚本打印了分割大块的命令,以及每个大块所在的碎片、块的大小和其中的文档数量。最后还会显示汇总信息。

dataSize命令中的estimate: true选项使它使用集合的平均文档大小进行估计。如果文档大小有很多差异,但运行速度更快,资源消耗更少,那么这不是很准确。如果您知道文档大小大致相同,请考虑设置该选项。

剩下的就是运行脚本生成的命令,大块应该就消失了。然后,平衡器将在下一个平衡窗口中根据需要移动数据块以均衡数据。考虑在高峰工作负载时间之外安排平衡窗口,以减少影响。

结论

尽管MongoDB 3.6已经EOL有一段时间了,但很多人仍然在运行它,主要是由于应用端过时的驱动程序与新版本不兼容。现在,autoSplitter应该在控制块大小方面做得更好。

如果您仍在运行比4.2更老的MongoDB版本,那么不时检查数据块统计是一个好主意,以避免一些令人讨厌的意外。

雷竞技下载官网Percona Distribution for MongoDB是一个免费的MongoDB数据库替代方案,为您提供一个单一的解决方案,它结合了来自开源社区的最好和最重要的企业组件,设计和测试可以一起工作。

今天就下载Mong雷竞技下载官网oDB的Percona发行版!

订阅
通知的
客人

0评论
内联反馈
查看所有注释