Elasticsearch的小技巧

关于Elasticsearch中的数据恢复小技巧的简短说明,对我本人而言。 如果没有备份,如何修复红色索引,删除文档并且没有副本,该怎么办-不幸的是,在官方文档中,它们没有任何提示。

后备




首先要做的是设置重要数据的备份。 官方文档中对此进行了说明

总而言之,没有什么复杂的。 在最简单的版本中,在另一台服务器上创建一个球,然后以任何方便的方式(nfs,smbfs等)将其安装到所有弹性节点上。 接下来,使用cron,您的应用程序或其他任何东西发送定期快照的请求。

第一个快照将很长,随后的快照将仅包含索引状态之间的增量。 请注意,如果定期执行强制合并 ,则增量将很大,因此创建快照所需的时间将与第一次相似。

注意事项:

  • 检查备份的状态,例如,使用_cat: curl localhost:9200/_cat/snapshots/ yourbackuprepo /部分失败快照不是您的兄弟。
  • 从ES 6.x开始,elastic对请求标头的要求非常高。 如果您手动执行这些操作(而不是通过API),请检查是否已设置Content-Type: application/json ,否则所有请求都将中断并且不会发生备份
  • 快照无法还原到打开的索引。 必须先关闭或卸下它。 但是,您可以使用rename_pattern,rename_replacement并排还原快照( 请参阅扩展坞中的示例 )。 此外,还原快照时,其设置也会还原,包括别名,副本数等。 如果您不需要这样做,请添加index_settings( 有关示例,请参见Dock ),并对还原请求进行必要的更改。
  • 带有快照的存储库(球)可以连接到多个群集,并将快照从任何群集还原到其他群集。 最主要的是弹性版本是兼容的。

通常,看一下文档,或多或少地公开了这个主题。

弹性转储




nodejs上的一个小实用程序 ,可让您将数据从一个索引复制到另一个索引,集群,文件,stdout。

顺便说一句,可以将输出到文件或stdout的方法用作备用备份方法-输出是常规的有效json(类似于sql dump),可以根据需要重复使用。 例如,您可以将输出粘贴在管道中,您的脚本将以某种方式在其中转换数据并将其发送到另一个存储库,例如clickhouse。 最简单的js转换可以直接由elasticdump本身完成,有一个对应的键--transform 。 一般来说,是一种幻想。

陷阱:

  • 作为备份方法,它比快照要慢得多。 另外,备份会随着时间的延长而扩展,因此频繁更改索引的结果可能会不一致。 请记住。
  • 不要使用来自debian仓库的nodejs,因为它的版本太旧会对工具的稳定性产生负面影响。
  • 稳定性可能会有所不同,尤其是当其中一方过载时。 不要尝试通过在办公计算机上运行该工具从一台服务器备份到另一台服务器-所有流量都将流经该服务器。
  • 无花果复制映射。 如果那里有些复杂,请手动创建索引,然后再将数据填充到其中。
  • 有时更改块的大小(参数--limit)很有意义。 此选项直接影响复制速度。

要同时合并大量索引,可以使用带有一组简化选项的multielasticdump,但是所有索引都是并行合并的。

注意! 该实用程序的作者说,他不再有时间支持,因此该程序正在寻找新的维护人员

根据个人经验:有用的工具,多次被救出。 速度和稳定性很一般,我希望有一个合适的替代产品,但是到目前为止,还没有任何东西。

检查索引


因此,我们开始接近阴暗面。 情况:索引变红了。 在日志中-出了点问题,支票与金额不符,您可能有内存或磁盘:

org.apache.lucene.index.CorruptIndexException: checksum failed (hardware problem?)

当然,这对于母亲管理员是永远不会发生的,因为他们拥有具有三重复制功能的高端硬件,可即时纠正所有错误级别的superECC内存,并且通常每秒配置一次快照。

但是不幸的是,现实有时会提示这样的选项,当备份时间相对较长时(如果您每小时索引了千兆字节,那么备份是否在2小时之前过旧了?),没有地方可以还原数据,复制没有时间和诸如此类的东西。

当然,如果有快照,备份等。 -非常好,推出,不用担心。 如果没有呢? 幸运的是,至少某些数据仍然可以保存。

首先,关闭索引和/或关闭弹性,制作故障分片的备份副本。

Lucene(即,它在elasticsearch中用作后端)具有出色的CheckIndex方法。 我们只需要在破碎的碎片上召唤它即可。 Lucene将检查所有分段,并删除损坏的分段。 是的,数据将丢失,但至少不会丢失所有数据。 虽然有多么幸运。

至少有两种方法。

方法1:直接在站点上


这样一个简单的脚本将对我们有所帮助。

 #!/bin/bash pushd /usr/share/elasticsearch/lib java -cp lucene-core*.jar -ea:org.apache.lucene... org.apache.lucene.index.CheckIndex "$@" popd 

在不带参数的情况下调用它,我们得到的是这样的:

 ERROR: index path not specified Usage: java org.apache.lucene.index.CheckIndex pathToIndex [-exorcise] [-crossCheckTermVectors] [-segment X] [-segment Y] [-dir-impl X] -exorcise: actually write a new segments_N file, removing any problematic segments -fast: just verify file checksums, omitting logical integrity checks -crossCheckTermVectors: verifies that term vectors match postings; THIS IS VERY SLOW! -codec X: when exorcising, codec to write the new segments_N file with -verbose: print additional details -segment X: only check the specified segments. This can be specified multiple times, to check more than one segment, eg '-segment _2 -segment _a'. You can't use this with the -exorcise option -dir-impl X: use a specific FSDirectory implementation. If no package is specified the org.apache.lucene.store package will be used. **WARNING**: -exorcise *LOSES DATA*. This should only be used on an emergency basis as it will cause documents (perhaps many) to be permanently removed from the index. Always make a backup copy of your index before running this! Do not run this tool on an index that is actively being written to. You have been warned! Run without -exorcise, this tool will open the index, report version information and report any exceptions it hits and what action it would take if -exorcise were specified. With -exorcise, this tool will remove any segments that have issues and write a new segments_N file. This means all documents contained in the affected segments will be removed. This tool exits with exit code 1 if the index cannot be opened or has any corruption, else 0. 

实际上,我们可以简单地运行索引测试,也可以使CheckIndex“修复”它,以消除所有损坏的东西。

Lucene索引的生存方式大致相同:/ var / lib / elasticsearch / nodes / 0 / indexs / str4ngEHashVa1uE / 0 / index /,其中0和0是服务器上的节点号和节点上的分片数。 它们之间的可怕值-索引的内部名称-可以从curl localhost的输出中获取:9200 / _cat / indexs。

我通常将副本复制到另一个目录,然后就地修复。 然后,我重新启动elasticsearch。 通常,所有内容都会被收集,尽管会丢失数据。 有时由于shards文件夹中的*损坏*文件,仍然不希望读取索引。 将它们移到安全的地方一会儿。

方法2:路加



(图片来自互联网)

与Lucene一起工作的实用工具叫做Luke

这里还是比较简单。 从您的elasticsearch中找出Lucene版本:

 $ curl localhost:9200 { "name" : "node00", "cluster_name" : "main", "cluster_uuid" : "UCbEivvLTcyWSQElOipgTQ", "version" : { "number" : "6.2.4", "build_hash" : "ccec39f", "build_date" : "2018-04-12T20:37:28.497551Z", "build_snapshot" : false, "lucene_version" : "7.2.1", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" } 

采取相同版本的卢克。 我们用daw在其中打开一个索引(当然是副本)。 不要打开IndexReader(打开损坏的索引时) 。 接下来,单击工具/检查索引。 首先,我建议空运转,然后再以维修模式运转。 进一步的操作类似-复制回弹性,重新启动/打开索引。

恢复已删除的文档


情况:您执行了破坏性查询,删除了很多/所有需要的数据。 而且无处可恢复,或者非常昂贵。 好吧,SSZB当然没有备份,但是这种情况也会发生。

不幸的是,Lucene从未直接删除任何东西。 它的理念更接近CoW,因此删除的数据实际上并未删除,而仅标记为已删除。 删除本身发生在索引优化过程中-分段中的实时数据被复制到新创建的分段中,旧分段仅被删除。 通常,尽管已删除索引的状态不为0,但仍有机会将其删除。

 $ curl localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open data.0 R0fgvfPnTUaoI2KKyQsgdg 5 1 7238685 1291566 45.1gb 22.6gb 

强制合并后就没有机会了。

因此,首先,关闭索引,停止弹性,将索引(文件)复制到安全的地方。

无法提取单个已删除的文档。 您只能恢复指定段中的所有已删除文档。

对于低于4的Lucene版本,一切都非常简单。 Lucene API具有一个称为undeleteAll的函数。 您可以从上一段直接从卢克(Luke)打电话给她。

new,对于较新的版本,该功能已被删除。 但是仍然有办法。 有关实时文档的信息存储在* .liv文件中。 但是,仅删除它们将使索引不可读。 您需要更正segments_N文件,以便它完全忘记它们的存在。

在您最喜欢的Hex编辑器中打开segments_N文件(N是整数)。 官方文档将帮助我们进行导航:
 segments_N: Header, LuceneVersion, Version, NameCounter, SegCount, MinSegmentLuceneVersion, <SegName, SegID, SegCodec, DelGen, DeletionCount, FieldInfosGen, DocValuesGen, UpdatesFiles>SegCount, CommitUserData, Footer 

所有这些,我们需要DelGen(Int64)和DeletionCount(Int32)的值。 第一个必须设置为等于-1,第二个设置为0。



找到它们并不难,它们就位于SegCodec的后面,这是一个非常引人注目的字符串,如Lucene62。 在此屏幕快照中,您可以看到DelGen的值为3,并且DeletionCount-184614。将第一个替换为0xFFFFFFFFFFFFFFFF,第二个替换为0x00000000。 重复所有必要的细分,保存。

但是,由于校验和错误,固定索引将不希望加载。 这里还是比较简单。 以Luke为例,使用禁用的IndexReader,工具/检查索引加载索引。 我们进行测试并立即发现segment_N已损坏。 这样的检查是期望的,但是这样的检查是可以接收的。

 Caused by: org.apache.lucene.index.CorruptIndexException: checksum failed (hardware problem?) : expected=51fbdb5c actual=6e964d17 

废话! 我们将预期的校验和输入到文件的最后4个字节中。



保存。 我们再次运行CheckIndex以确保一切正常,并且索引正在加载。

等等!

Source: https://habr.com/ru/post/zh-CN416955/


All Articles