故障排除损坏
编辑故障排除损坏编辑
Elasticsearch 期望从磁盘读取的数据与之前写入的数据完全一致。如果检测到磁盘上的数据与写入的数据不同,它将报告某种异常,例如
-
org.apache.lucene.index.CorruptIndexException
-
org.elasticsearch.gateway.CorruptStateException
-
org.elasticsearch.index.translog.TranslogCorruptedException
通常,这些异常是由于校验和不匹配造成的。Elasticsearch 写入磁盘的大多数数据后面都跟着一个使用简单算法(称为 CRC32)计算的校验和,该算法计算速度快,并且擅长检测使用有故障存储时可能发生的随机损坏。CRC32 校验和不匹配肯定表明存在故障,当然,匹配的校验和并不能证明没有损坏。
验证校验和很昂贵,因为它涉及读取文件的每个字节,这需要大量的努力,并且可能会将更有用的数据从文件系统缓存中驱逐出去,因此系统通常不会经常验证文件的校验和。这就是为什么您往往只会在发生异常情况时遇到损坏异常的原因。例如,在合并、分片移动和快照期间经常检测到损坏。这并不意味着这些过程会导致损坏:它们是需要读取整个文件时罕见情况的示例。Elasticsearch 利用这个机会同时验证校验和,这就是检测和报告损坏的时间。它不指示损坏的原因或发生时间。损坏可能在几个月内都无法被检测到。
构成 Lucene 索引的文件是从头到尾顺序写入的,然后不再修改或覆盖。这种访问模式意味着校验和计算非常简单,可以在最初写入文件时动态进行,并且也使得错误的校验和不太可能是由于文件写入时用户空间错误造成的。计算校验和的 Elasticsearch 部分非常简单,使用广泛,并且经过了充分的测试,因此您可以非常自信地认为校验和不匹配确实表明从磁盘读取的数据与 Elasticsearch 之前写入的数据不同。
如果文件头损坏,则 Elasticsearch 可能无法确定如何开始读取文件,这会导致以下异常:
-
org.apache.lucene.index.IndexFormatTooOldException
-
org.apache.lucene.index.IndexFormatTooNewException
如果 Elasticsearch 需要的文件完全丢失,它也可能会报告损坏,并出现以下异常:
-
java.io.FileNotFoundException
-
java.nio.file.NoSuchFileException
构成 Lucene 索引的文件在使用之前会完整写入。如果在重启后恢复索引需要一个文件,那么您的存储系统之前已向 Elasticsearch 确认该文件已持久同步到磁盘。在 Linux 上,这意味着 fsync()
系统调用已成功返回。Elasticsearch 有时会报告索引损坏,因为恢复所需的某个文件丢失,或者存在但已被截断或缺少其页脚。这可能表明您的存储系统错误地确认了持久写入。
Elasticsearch 在您的集群中检测到损坏有很多可能的解释。像 Elasticsearch 这样的数据库会生成具有挑战性的 I/O 工作负载,这可能会发现其他测试可能遗漏的细微基础设施问题。已知 Elasticsearch 会将以下问题暴露为文件损坏
- 文件系统错误,尤其是在较新和非标准文件系统中,这些文件系统可能没有经过足够的真实世界生产使用,无法确定它们是否正常工作。
- 内核错误.
- 驱动器或 RAID 控制器上运行的固件中的错误。
- 配置错误,例如将
fsync()
配置为在所有持久写入完成之前报告成功。 - 硬件故障,可能包括驱动器本身、RAID 控制器、RAM 或 CPU。
- 修改 Elasticsearch 写入文件的第三方软件。
数据损坏通常不会导致除校验和不匹配之外的其他问题证据。不要将此解释为您的存储子系统正常工作,因此 Elasticsearch 本身导致了损坏的迹象。有故障的存储很少会显示除数据损坏之外的任何问题证据,但数据损坏本身是您的存储子系统无法正常工作的非常强烈的指标。
为了排除 Elasticsearch 作为数据损坏来源的可能性,请使用除 Elasticsearch 之外的其他工具生成 I/O 工作负载,并查找数据完整性错误。在 Linux 上,fio
和 stress-ng
工具都可以生成具有挑战性的 I/O 工作负载,并验证它们写入数据的完整性。使用 stress-ng
的 0.12.01 或更高版本,因为早期版本没有足够强的完整性检查。使用诸如 diskchecker.pl
之类的脚本验证持久写入是否在断电后仍然存在。或者,使用诸如 strace
之类的工具来观察 Elasticsearch 在写入数据时执行的系统调用序列,并确认此序列不会解释报告的损坏。
为了缩小损坏来源的范围,请系统地更改集群环境中的组件,直到损坏停止。具体细节将取决于您环境的确切配置,但可能包括以下内容
- 尝试不同的文件系统或不同的内核。
- 尝试依次更改每个硬件组件,理想情况下更改为不同的型号或制造商。
- 尝试每个硬件组件的不同固件版本。
- 删除可能修改 Elasticsearch 数据路径内容的任何第三方软件。