📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 7.x-8.x

1. 错误异常的基本描述 #

failed to find existing translog files 表示 Elasticsearch 在处理损坏分片或恢复分片时,尝试读取 translogPath 目录中的现有 translog 文件,但在列目录阶段就抛出了 IOException

这不是查询层错误,而是分片存储层错误。异常通常出现在 translog 工具、损坏分片清理或底层恢复流程中。

常见现象 #

  • 分片恢复、节点启动或损坏分片清理失败,Elasticsearch 日志中出现 failed to find existing translog files 异常。
  • 服务端日志里同时出现 IOException、路径访问失败、权限错误或文件系统报错。
  • 同一分片可能伴随 all shards failed、索引不可恢复或 translog 损坏类报错。
  • 使用 elasticsearch-shard 工具执行 remove-corrupted-data 时,命令执行失败并输出该异常。

典型报错与异常栈 #

org.elasticsearch.ElasticsearchException: failed to find existing translog files
Caused by: java.io.IOException: No such file or directory
    at java.io.UnixFileSystem.list(Native Method)
    at org.elasticsearch.index.translog.Translog.filesInDirectory(Translog.java:XXX)
org.elasticsearch.ElasticsearchException: failed to find existing translog files
Caused by: java.nio.file.AccessDeniedException: /var/lib/elasticsearch/nodes/0/indices/XXX/0/translog

2. 为什么会发生这个错误 #

从源码看,异常直接包裹在 filesInDirectory(translogPath) 外层。也就是说,真正失败点不是"没找到某个 translog 条目",而是 Elasticsearch 连 translog 目录都无法正常枚举。

Translog 是 Elasticsearch 保障数据可靠性的核心机制:每次写入操作先写入 translog 再写入 Lucene 索引,节点重启时通过重放 translog 恢复未刷盘的数据。如果 translog 目录本身无法访问,分片恢复流程将直接中断。

常见原因包括:

  • 分片目录缺失或不完整:分片目录被手工删除、迁移不完整,或挂载卷未正确挂载,导致 translog 目录物理上不存在。
  • 权限问题:Elasticsearch 进程对 translog 目录没有读取或执行权限,常见于目录权限被误改或数据目录被其他用户重新创建。
  • 磁盘或文件系统故障:磁盘故障、文件系统损坏、只读挂载(read-only)或底层 I/O 错误导致目录访问失败。
  • 运维误操作:运维脚本在节点运行期间误删了 translog 文件或上层目录,例如直接清理 data/ 目录下的文件。
  • 节点异常退出后的残留状态:节点被 kill -9 强制终止后,数据目录状态不一致,重启时触发恢复逻辑但 translog 目录已损坏。

3. 如何排查这个异常 #

建议按以下顺序排查:

  1. 定位分片路径:根据日志中的索引名、分片号和节点路径,定位实际的 translog 目录,默认路径类似:
    # 路径格式
    $ES_DATA_DIR/nodes/0/indices/<index_uuid>/<shard_id>/translog
    
  2. 检查目录是否存在:在节点上执行:
    ls -la /var/lib/elasticsearch/nodes/0/indices/<index_uuid>/<shard_id>/translog
    

    如果目录不存在,说明分片数据已丢失或被误删。

  3. 检查目录权限:确认目录的属主和权限是否正确:
    ls -ld /var/lib/elasticsearch/nodes/0/indices/<index_uuid>/<shard_id>/translog
    # 应归属于运行 Elasticsearch 的用户(如 elasticsearch)
    
  4. 检查磁盘和文件系统状态
    # 检查磁盘是否只读
    mount | grep "read-only"
    # 检查磁盘空间
    df -h /var/lib/elasticsearch
    # 检查文件系统错误(需要 umount)
    dmesg | grep -i "error\|readonly\|I/O"
    
  5. 查看系统日志:确认是否存在磁盘 I/O、文件系统只读或设备异常:
    journalctl -xe | grep -i "read-only\|io error\|ext4\|xfs"
    
  6. 确认分片是否有副本或快照:如果这是恢复或修复流程的一部分,先确认该分片是否已有可用副本或快照,避免盲目删除数据。

排查时需要注意的问题 #

  • 不要直接在运行中的 Elasticsearch 节点上删除或修改 data/ 目录下的文件,这会导致分片状态不一致。
  • 如果节点以 readonly 模式挂载了数据盘,Elasticsearch 可能无法枚举目录内容,此时 IOException 是正常现象。
  • 多个分片同时报错时,优先考虑磁盘或挂载点问题,而非单个分片的问题。
  • 使用 elasticsearch-shard 工具前,务必先停止目标节点上的 Elasticsearch 进程,避免数据进一步损坏。

4. 如何解决这个错误 #

常用修复思路 #

方案一:修复目录访问问题(目录存在但无法访问)

# 修复权限
chown -R elasticsearch:elasticsearch /var/lib/elasticsearch/nodes/0/indices/<index_uuid>/<shard_id>/translog
chmod 755 /var/lib/elasticsearch/nodes/0/indices/<index_uuid>/<shard_id>/translog

# 如果磁盘只读,重新挂载为可写
mount -o remount,rw /var/lib/elasticsearch

方案二:从副本自动恢复(推荐)

如果索引配置了副本(number_of_replicas >= 1),将当前节点移出集群后重新加入,Elasticsearch 会从其他副本自动恢复分片:

# 临时将节点排除出集群(在集群中任意正常节点执行)
curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d'
{
  "transient": {
    "cluster.routing.allocation.exclude._name": "<故障节点名>"
  }
}'

# 修复后取消排除
curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d'
{
  "transient": {
    "cluster.routing.allocation.exclude._name": null
  }
}'

方案三:使用 shard 工具删除损坏数据(无副本时慎用)

# 停止 Elasticsearch 进程后执行
sudo -u elasticsearch bin/elasticsearch-shard remove-corrupted-data \
  --index <index_name> \
  --shard-id 0

# 注意:此操作会丢失 translog 中未刷盘的数据

方案四:从快照恢复

# 关闭索引
curl -X POST "localhost:9200/<index_name>/_close"

# 从快照恢复
curl -X POST "localhost:9200/_snapshot/<repo_name>/<snapshot_name>/_restore" \
  -H "Content-Type: application/json" -d'
{
  "indices": "<index_name>",
  "include_global_state": false
}'

后续注意事项与推荐建议 #

  • 为索引设置至少 1 个副本(number_of_replicas: 1),确保单节点故障时数据可恢复。
  • 定期执行快照备份,验证快照完整性,避免数据丢失后无备份可用。
  • 监控磁盘使用率、inode 使用率和文件系统只读状态,设置告警阈值。
  • 禁止在 Elasticsearch 运行时对 data/ 目录执行任何手工删除或移动操作。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 适合查看集群健康度、节点指标、索引状态、分片分配情况和磁盘使用趋势,帮助快速判断异常是局部问题还是系统性问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和流量治理,减少因写入风暴导致的节点异常和 translog 堆积。
  • 建议将节点磁盘、JVM、分片状态和恢复进度统一接入监控面板,在分片恢复失败前提前预警。

5. 小结 #

failed to find existing translog files 的核心含义是"存储层无法读取 translog 目录",不是普通字段或请求错误。排查重点应放在分片数据路径、权限、磁盘和文件系统,而不是 DSL 或客户端请求。

只要把磁盘监控、副本策略和快照备份结合起来,大多数 translog 相关的分片恢复问题都可以快速定位并修复,也更容易通过 INFINI Console 和 INFINI Gateway 实现持续预警与防护。

相关错误 #

附:日志上下文 #

// Hold the lock open for the duration of the tool running
Set translogFiles;
try {
    translogFiles = filesInDirectory(translogPath);
} catch (IOException e) {
    throw new ElasticsearchException("failed to find existing translog files", e);
}
final String details = deletingFilesDetails(translogPath, translogFiles);
return Tuple.tuple(RemoveCorruptedShardDataCommand.CleanStatus.CORRUPTED, details);