有没有更聪明的方法来重新索引弹性搜索?

时间:2012-12-13 00:24:30

标签: ruby-on-rails elasticsearch

我问,因为我们的搜索处于不稳定的状态,因为我们解决了问题,但每次我们对索引进行更改(更改标记器或过滤器,或者碎片/副本的数量)时,我们必须吹走整个索引并将我们所有的Rails模型重新索引回Elasticsearch ...这意味着我们必须考虑停机时间来重新索引所有记录。

有没有一种更聪明的方法可以做到这一点,我不知道?

4 个答案:

答案 0 :(得分:70)

我认为@karmi做对了。但是,让我解释一下它有点简单。我需要偶尔使用一些新属性或分析设置升级生产模式。 我最近开始使用下面描述的方案来进行实时,恒定负载,零停机索引迁移。你可以远程做到这一点。

以下是步骤:

假设:

  • 你有索引real1和别名real_writereal_read指向它,
  • 客户端仅向real_write写入,仅从real_read
  • 读取 文件的
  • _source属性可用。

1。新索引

使用您选择的新映射和设置创建real2索引。

2。 Writer别名开关

使用以下批量查询切换写别名。

curl -XPOST 'http://esserver:9200/_aliases' -d '
{
    "actions" : [
        { "remove" : { "index" : "real1", "alias" : "real_write" } },
        { "add" : { "index" : "real2", "alias" : "real_write" } }
    ]
}'

这是原子操作。从这时起,real2将在所有节点上填充新客户端的数据。读者仍然通过real1使用旧real_read。这是最终的一致性。

3。旧数据迁移

必须将数据从real1迁移到real2,但real2中的新文档无法用旧条目覆盖。迁移脚本应使用bulk API和create操作(不是indexupdate)。我使用简单的Ruby脚本es-reindex,它有很好的E.T.A.状态:

$ ruby es-reindex.rb http://esserver:9200/real1 http://esserver:9200/real2

2017年更新您可以考虑使用新的Reindex API而不是使用该脚本。它有许多有趣的功能,如冲突报告等。

4。读者别名开关

现在real2是最新的,客户正在写信,但他们仍在阅读real1。让我们更新读者别名:

curl -XPOST 'http://esserver:9200/_aliases' -d '
{
    "actions" : [
        { "remove" : { "index" : "real1", "alias" : "real_read" } },
        { "add" : { "index" : "real2", "alias" : "real_read" } }
    ]
}'

5。备份和删除旧索引

写入和读取转到real2。您可以从ES群集备份和删除real1索引。

完成!

答案 1 :(得分:30)

是的,有更智能的方法可以在不停机的情况下重新索引数据。

首先,永远不要使用“最终”索引名称作为真正的索引名称。因此,如果您想将索引命名为“文章”,请不要将该名称用作物理索引,而是创建索引,例如“articles-2012-12-12”或“articles-A”,“文章” -1“等等。

其次,创建指向该索引的别名“alias”。然后,您的应用程序将使用此别名,因此您永远不需要手动更改索引名称,重新启动应用程序等。

第三,当你想要或需要重新索引数据时,将它们重新索引到不同的索引,让我们说“articles-B”--Tire索引工具链支持中的所有工具你在这里。

完成后,将别名指向新索引。通过这种方式,您不仅可以最大限度地减少停机时间(没有任何停机时间),还可以获得安全快照:如果您以某种方式将索引编入新索引,您可以切换回旧索引,直到您解决问题。

答案 2 :(得分:3)

写了一篇关于我如何处理重新索引的博客文章,最近没有停机时间。需要一些时间来弄清楚所有需要做的小事情。希望这有帮助!

https://summera.github.io/infrastructure/2016/07/04/reindexing-elasticsearch.html

总结:

第1步:准备新索引

使用新映射创建新索引。这可以在Elasticsearch的同一个实例上,也可以在全新的实例上。

第2步:保持索引最新

在重新编制索引时,您希望保持新旧索引的最新状态。对于写操作,可以通过将写操作发送到新旧索引上的后台工作程序来完成。

删除有点棘手,因为删除和重新索引记录到新索引之间存在竞争条件。因此,您需要跟踪在重新索引期间需要删除的记录,并在完成后处理这些记录。如果您没有执行多次删除操作,另一种方法是在重新索引期间消除删除的可能性。

第3步:执行重建索引

您需要使用scrolled search来读取数据,并使用bulk API进行插入。由于在第2步之后您将在后台编写新的和更新的文档到新索引,因此您需要确保不使用批量API请求更新新索引中的现有文档。

这意味着您希望批量API请求的操作是创建,而不是索引。从documentation:“如果已存在具有相同索引和类型的文档,则create将失败,而index将根据需要添加或替换文档”。这里的要点是您不希望滚动搜索快照中的旧数据覆盖新索引中的新数据。

github上有一个很棒的脚本来帮助你完成这个过程:es-reindex

第4步:切换

完成重建索引后,就可以将搜索切换到新索引了。您需要重新打开删除或处理新索引的排队删除作业。您可能会注意到,首先搜索新索引有点慢。这是因为Elasticsearch和JVM需要时间来预热。

执行您需要的任何代码更改,以便您的应用程序开始搜索新索引。如果遇到问题并需要回滚,可以继续写入旧索引。如果您觉得这是不必要的,您可以停止写信。

第5步:清理

此时您应该完全转换到新索引。如果一切顺利,请执行任何必要的清理,例如:

  • 删除旧索引主机(如果它与新
  • 不同)
  • 删除与旧索引相关的序列化代码

答案 3 :(得分:2)

也许创建另一个索引,并将所有数据重新索引到那个索引上,然后在重新编制索引时进行切换?