MongoDB 在添加已填充集合的新分片时无法正确缩放

MongoDB doesn't scale properly when adding new shard with collection already filled

我的 MongoDB 分片集群摄取性能在添加新分片时没有扩展。

我有一个小型集群设置,其中包含 1 mongos + 1 个配置副本集(3 个节点)+ N 个分片副本集(每个 3 个节点)。

Mongos 在一个专用的 Kubernetes 节点上,每个 mongo 托管分片的进程都有其专用的 k8s 节点,而配置 mong 处理 运行 一些恰好部署的地方.

集群主要用于GridFS文件托管,典型文件100Mb左右

我正在对 1、2 和 3 个分片进行压力测试,看看它是否可以正确扩展,但它没有。

如果我用 2 个分片启动一个全新的集群并且 运行 我的测试它以(大约)两倍于我用 1 个分片的速度摄取文件,但是如果我用 1 个分片启动集群,那么执行测试,然后再添加 1 个分片(总共 2 个分片),然后再次执行测试,摄取速度与之前使用 1 个分片的速度大致相同。

查看块的去向,当我立即使用 2 个分片启动集群时,分片之间的负载均衡。 如果我从 1 个分片开始并在一些插入后添加第二个分片,那么这些块往往会全部放在旧分片上,平衡器必须稍后将它们带到第二个分片。

速览:

这是由于哈希分片和平衡的工作原理。

在空集合中(来自 Shard an Empty Collection):

The sharding operation creates empty chunks to cover the entire range of the shard key values and performs an initial chunk distribution. By default, the operation creates 2 chunks per shard and migrates across the cluster.

因此,如果您在具有 x 个分片的集群上执行 sh.shardCollection(),它将为每个分片创建 2 个块并将它们分布在各个分片中,总共 2x 个块簇。由于集合是空的,因此移动块几乎不需要时间。您的摄取现在将均匀分布在各个分片中(假设其他情况,例如散列字段的基数良好)。

现在,如果您在 创建块后添加一个新分片 ,该分片开始时为空,平衡器将开始使用 Migration Thresholds 向其发送块。在已填充的集合中,此过程可能需要一段时间才能完成。

如果当平衡器仍在四处移动块(现在可能不是空的)时您进行了另一次摄取,则集群现在同时执行两项不同的工作:1) 摄取和 2) 平衡。

当您对 1 个分片执行此操作并添加另一个分片时,您正在摄取的块很可能仍位于分片 1 中并且尚未移动到新分片,因此大多数数据将进入那个碎片。

因此,您应该等到添加新分片后集群达到平衡,然后再进行另一次摄取。平衡后,摄取负载应该更均匀地分布。

注意: 由于您的分片键是 file_id,我假设每个文件的大小大致相同 (~100 MB)。如果某些文件比其他文件大得多,则某些块也会比其他块更忙。