添加已填充集合的新分片时,MongoDB无法正确扩展

Fed*_*lli 5 sharding mongodb gridfs kubernetes

添加新的分片时,我的MongoDB分片的群集接收性能无法提高。

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

Mongos在一个专用的Kubernetes节点上,每个托管碎片的mongo进程都有其专用的k8s节点,而config mong进程在它们恰好部署于此的地方运行。

该群集主要用于GridFS文件托管,典型文件约为100Mb。

我正在使用1个,2个和3个分片进行压力测试,以查看它是否可以正确缩放,但不能缩放。

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

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

要闻速览:

  • 块大小1024 MB

  • 分片键是GridFS file_id,已散列

kev*_*adi 2

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

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

分片操作创建空块以覆盖分片键值的整个范围并执行初始块分配。默认情况下,该操作为每个分片创建 2 个块并跨集群迁移。

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

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

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

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

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

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