有没有更聪明的方法来重新索引elasticsearch?
我问,因为我们的search处于不断变化的状态,但是每当我们对索引进行更改(更改标记器或filter,或者分片/副本的数量)时,我们不得不吹掉整个索引,将所有Rails模型重新索引到Elasticsearch中…这意味着我们必须考虑停机时间来重新索引所有logging。
有没有更聪明的方法来做到这一点,我不知道?
我认为@卡尔米是正确的。 不过,让我解释一下更简单一些。 我需要偶尔使用一些新的属性或分析设置升级生产模式。 我最近开始使用下面描述的场景来进行实时,恒定负载,零停机索引迁移。 你可以远程做到这一点。
这里是步骤:
假设:
- 你有索引
real1
和别名real_write
,real_read
指向它, - 客户端只写入
real_write
,只读real_read
, - 文档的
_source
属性可用。
1.新的索引
使用您select的新映射和设置创buildreal2
索引。
2.编写器别名开关
使用以下批量查询开关写入别名。
curl -XPOST 'http://esserver:9200/_aliases' -d ' { "actions" : [ { "remove" : { "index" : "real1", "alias" : "real_write" } }, { "add" : { "index" : "real2", "alias" : "real_write" } } ] }'
这是primefaces操作。 从这个时候开始, real2
在所有节点上都填充了新的客户端数据。 读者仍然通过real_read
使用旧的real_read
。 这是最终的一致性。
3.旧数据迁移
数据必须从real1
迁移到real2
,但real2
中的新文档不能被旧条目覆盖。 迁移脚本应使用bulk
API与create
操作(而不是index
或update
)。 我使用简单的Ruby脚本es-reindex ,它具有很好的ETA状态:
$ ruby es-reindex.rb http://esserver:9200/real1 http://esserver:9200/real2
更新2017年你可能会考虑新的Reindex API,而不是使用脚本。 它有很多有趣的function,如冲突报告等
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
索引。
完成!
是的,如何在没有停机的情况下重新build立索引数据,有更明智的方法。
首先,永远不要使用“最终”索引名称作为真正的索引名称。 因此,如果您想要将索引命名为“文章”,请不要将该名称用作物理索引,而应创build一个索引,如“articles-2012-12-12”或“articles-A”,“articles -1“等
其次,创build一个指向该索引的别名“别名”。 您的应用程序将使用此别名,因此您将永远不需要手动更改索引名称,重新启动应用程序等。
第三,当你想要或者需要重新索引数据时,将它们重新索引到一个不同的索引中 ,比如说“articles-B”–Tire的索引工具中的所有工具都支持你。
完成后,将别名指向新的索引。 通过这种方式,不仅可以最大限度地减less停机时间(不存在任何问题),还可以获得安全的快照:如果以某种方式将索引搞乱了,可以切换回旧索引,直到解决问题。
写了一篇关于我如何处理reindexing而不是最近没有停机的博客文章。 花费一些时间来弄清所有需要到位的小事情。 希望这可以帮助!
https://summera.github.io/infrastructure/2016/07/04/reindexing-elasticsearch.html
总结:
步骤1:准备新的索引
用你的新映射创build你的新索引。 这可以在Elasticsearch的同一个实例上,也可以在一个全新的实例上。
第2步:保持索引最新
当你重新索引时,你希望保持你的新旧索引是最新的。 对于写入操作,这可以通过将写入操作发送到新老索引上的后台工作者来完成。
删除有点棘手,因为删除和重新索引logging到新索引之间存在争用条件。 因此,您需要跟踪在reindex期间需要删除的logging,并在完成后处理这些logging。 如果你没有执行很多删除操作,另一种方法是在你的reindex期间消除删除的可能性。
步骤3:进行重生
您需要使用滚动式search来读取数据和批量API以进行插入。 由于在步骤2之后,您将在后台将新的和更新的文档写入新的索引,您希望确保不会使用批量API请求更新新索引中的现有文档。
这意味着您要批量处理API请求的操作是创build,而不是索引。 从文档 :“如果已经存在具有相同索引和types的文档,则创build将失败,而索引将根据需要添加或replace文档”。 这里的要点是你不希望滚动的search快照中的旧数据覆盖新索引中的新数据。
github上有一个很棒的脚本来帮助你完成这个过程: es-reindex 。
第四步:切换
完成重新索引后,就可以将search切换到新索引。 您需要重新打开删除或处理新索引的入队删除作业。 您可能会注意到,search新索引起初有点慢。 这是因为Elasticsearch和JVM需要时间热身。
执行您需要的任何代码更改,以便您的应用程序开始search新的索引。 您可以继续写入旧索引,以防止遇到问题并需要回滚。 如果你觉得这是不必要的,你可以停止写信给它。
第5步:清理
此时你应该完全转换到新的索引。 如果一切进展顺利,请执行任何必要的清理,例如:
- 删除旧的索引主机,如果它不同于新的
- 删除与旧索引相关的序列化代码
也许创build另一个索引,并将所有数据重新索引到该索引,然后在重新索引时进行切换?