Elasticsearch:像Pro一样的切换索引
#database #elasticsearch

介绍

搜索大型文档的最常用数据库之一是弹性搜索。有特定的机制可以显着加快搜索的速度。但是,必须明智地设置配置,否则,您的搜索需要比预期的要长得多。

背景(弹性搜索概念)

Elastic Search Cluster with Index and Shards

节点

数据分布在多个计算实例上,称为节点,以并行化搜索并更快。因此,每个实例只有整个数据库的一小部分。

主要碎片

数据是在索引中组织的,可以将其与SQL数据库中的表进行比较。例如,如果您是体育网站,则有针对球员,团队或比赛的指数。每个索引的数据分为主要碎片,以便一个碎片可以保留在一个节点上。
您已经意识到,主碎片的数量不应高于节点的数量,否则我们在一个节点上有2个单独的碎片,这效率较低。

复制碎片

Replica shards add redundancy to the index

认为我们有一个带有5个碎片的播放器索引,其中有5个节点,其中shard 1在节点1上,依此类推。假设节点1忙于在另一个索引中搜索。如果您现在想搜索玩家,则shard 1(在繁忙的节点1上)可能会延迟响应。
为了克服这一点,我们介绍了复制碎片:每个碎片可以具有0-N复制品,其中包含与相应碎片完全相同的数据。他们应该躺在另一个节点上。在我们的示例中,考虑shard 1的副本1在节点2上,我们还可以解决节点2并跳过繁忙的节点1。

问题

我们经历了我们的节点的CPU利用率在高峰时段急剧增加,并且弹性搜索无法处理所有搜索请求。解决搜索请求的时间分配给每个节点上的请求,碎片中的实际搜索,并收集结果以汇总它们。
实际搜索不能是问题,因为每个主碎片仅包含几百MB,所需的尺寸至少应为几个GB。因此,我们假设分裂和聚合可能是系统的更大开销。结果,我们需要减少节点和碎片的数量,以查看我们的假设是否正确。

不幸的是,不可能更新现有索引的碎片数。

解决方案

当前设置

  • 6个节点
  • 6个带有<1GB数据的索引
    • 5个主要碎片
    • 每碎1副本

要求

更改碎片的数量不仅仅是翻转开关。因此,我们需要确保生产系统仍然响应。

接近零停机时间,将来的数据量增加,集群应能够再次扩展

执行

有几种处理这种情况的方法。最后,我们决定在弹性搜索中使用别名的概念。

别名

别名是指向现有索引的指针。例如,别名成员指向 player 索引。现在,对会员别名的任何请求都将重定向到 player 索引。与索引相比,创建和删除索引非常容易。您不能创建具有与索引相同名称的别名。然而,创建别名和删除索引可能同时发生。我们使用这种行为。

过程

How to change an index in 3 steps

  1. 创建一个具有名称以及所需副本和主碎片大小的新索引。

    PUT /new_index
    {
      "settings": {
        "index": {
          "number_of_shards": 3,  
          "number_of_replicas": 2 
        }
      }
    }
    
  2. 将数据复制到。使用弹性搜索中的Reindex API调用。

    POST _reindex
    {
      "source": {
        "index": "old_index"
      },
      "dest": {
        "index": "new_index"
      }
    }
    
  3. 重定向和清理

    a。删除并创建一个名称
    的别名

    ```json
    POST /_aliases
      "actions": [
        {
          "add": {
            "index": "new_index",
            "alias": "old_index"
          }
        },
        {
          "remove_index": {
            "index": "old_index"
          }
        }
      ]
    }
    ```
    

    b。如果您已经有一个别名,请将其重定向到

    ```json
    POST /_aliases
      "actions": [
        {
          "add": {
            "index": "new_index",
            "alias": "old_index"
          }
        },
            {
          "remove": {
            "index": "other_index",
            "alias": "old_index"
          }
        },
        {
          "remove_index": {
            "index": "old_index"
          }
        }
      ]
    }
    ```
    

标志

为了使该方法可测试您可以在脚本中添加标志,从而使过程的每个部分可选。因此,您可以创建一个新的临时索引并从该索引切换。这不会影响您的生产环境,但是您可以测试过程的每个步骤。这是一个示例:

  1. 从现有的添加新的临时索引和reindex,但没有开关(1.和2.流程的步骤)
  2. 执行临时索引上的所有步骤。您可以选择在该索引上运行负载测试,以查看切换索引时是否没有停机时间。
  3. 看看一切是否按预期工作,以及您的服务是否经历过任何停机时间
  4. 删除新索引,因为它只是用于测试(仅第3步)

再次切换索引

您可能会问自己:如果我想再次更改碎片数,我该怎么做?没问题,只需使用步骤3.b,它考虑了您已经创建了一个别名。

结论

我向您展示了如何在不中断服务的情况下更改索引的设置。您可以创建一个新的索引,复制所有数据,并创建一个别名,在删除旧索引时指向您的新索引。

  • 您必须停机,因为切换索引并删除旧索引同时发生。
  • 测试没有问题,因为您可以启用和禁用每个步骤并创建临时索引。
  • 该过程可以多次应用,因为它也与现有的别名一起使用。
  • 使用cat endpoint实时监视该过程

不要害怕缩放

我们将碎片数减少到1个复制品和3个节点(在5个带有1个副本和5个节点的主碎片之前)。 CPU利用率降低了75%,成本降低了20%。

我希望我能帮助您充分利用弹性搜索集群。如果您有任何疑问,请告诉我,我很乐意回答他们。我将感谢您每天都学习的任何反馈。非常感谢!

参考