代码之家  ›  专栏  ›  技术社区  ›  Federico Bonelli

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

  •  1
  • Federico Bonelli  · 技术社区  · 5 年前

    添加新碎片时,我的MongoDB碎片群集接收性能不会放大。

    我有一个小的集群设置,有1个mongos+1个config副本集(3个节点)+N个shards副本集(每个3个节点)。

    Mongos位于一个专用的Kubernetes节点上,每个托管shard的mongo进程都有其专用的k8s节点,而config mong进程在它们碰巧部署的地方运行一段时间。

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

    我正在用1,2和3个碎片做压力测试,看它是否能正常伸缩,但它不能。

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

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

    简要事实:

    • 块大小1024 MB

    • 切分键是GridFS文件,散列

    0 回复  |  直到 5 年前
        1
  •  2
  •   kevinadi    5 年前

    这是因为散列切分和平衡是如何工作的。

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

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

    所以如果你执行 sh.shardCollection() 在群集中 x 碎片数量,它将为每个碎片创建2个块,并将它们分布到各个碎片上,总计 2x 集群中的块。因为集合是空的,所以移动块只需要很少的时间。你的摄取量现在将均匀地分布在碎片上(假设其他情况,例如哈希字段的基数很好)。

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

    如果在平衡器仍在移动块(现在可能不是空的)的同时执行另一个摄取,那么集群现在同时执行两个不同的任务:1)摄取,2)平衡。

    当你用一个碎片做这个并添加另一个碎片时,很可能你摄入的数据块仍然位于碎片1中,并且还没有移动到新的碎片,所以大多数数据将进入该碎片。

    因此,在添加新碎片之后,您应该等到集群达到平衡后再执行另一次摄取。平衡后,摄入的负荷应该更均匀地分布。

    注: 因为你的碎片钥匙是 file_id ,我假设每个文件的大小大致相同(100 MB)。如果一些文件比其他文件大得多,那么一些块也会比其他文件更忙。