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

适用版本: 6.8-8.9

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

failed to create empty store 出现在分片恢复(recovery)阶段。当 Elasticsearch 尝试为一个分片初始化空的底层存储目录时,如果 store.createEmpty() 调用失败,就会抛出 IndexShardRecoveryException

这不是搜索请求错误,而是分片恢复或初始化底层目录失败,通常发生在以下场景:

  • 新分片分配(primary 或 replica)
  • 分片恢复(节点重启后、集群扩容、节点间分片迁移)
  • 快照恢复(从快照还原索引时)

常见现象 #

  • 分片状态长期处于 INITIALIZINGUNASSIGNED,无法完成恢复。
  • 节点日志中反复出现 failed to create empty store 异常,伴随 IndexShardRecoveryException
  • 集群健康状态变为 yellowred,受影响的索引分片无法上线。
  • 有时还会伴随 IOExceptionAccessDeniedExceptionFileSystemException 等底层异常。

典型报错与异常栈 #

org.elasticsearch.indices.recovery.IndexShardRecoveryException: failed to create empty store
Caused by: org.elasticsearch.EngineException: failed to create engine
Caused by: java.io.IOException: failed to create empty directory
at org.elasticsearch.index.store.Store.createEmpty(Store.java:XXX)

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

failed to create empty store 的根本触发点是底层 store 初始化失败,而不是索引写入逻辑本身。常见原因包括:

  • 数据目录权限问题:Elasticsearch 进程对 path.data 配置的数据目录没有写权限,或目录属主不正确。
  • 磁盘空间不足:节点磁盘使用率过高,导致无法创建新文件或目录。
  • 文件系统只读:磁盘或文件系统被挂载为只读模式(如 read-only file system 错误)。
  • 磁盘 I/O 异常:底层存储出现 I/O 错误、坏道或硬件故障。
  • inode 耗尽:文件系统 inode 用完,无法创建新文件,即使磁盘空间还有剩余。
  • 路径配置错误elasticsearch.ymlpath.data 配置的路径不存在或不可访问。
  • 并发恢复冲突:多个分片同时恢复时,底层目录创建发生竞争或冲突。
  • 残留文件干扰:之前异常中断的恢复留下了不完整或半初始化的目录结构。

3. 如何排查这个异常 #

建议按以下顺序进行排查:

  1. 检查节点日志:在报错节点上查看 Elasticsearch 日志,确认完整的异常栈和 Caused by 信息,定位是权限、磁盘还是 I/O 问题。
  2. 检查数据目录权限:确认 path.data 目录的属主和权限,Elasticsearch 进程用户必须有读写执行权限。
    ls -la /path/to/elasticsearch/data/
    
  3. 检查磁盘空间和使用率
    df -h
    df -i    # 检查 inode 使用情况
    
  4. 检查文件系统状态:确认磁盘没有被挂载为只读。
    mount | grep <disk>
    dmesg | tail -50    # 查看是否有磁盘 I/O 错误
    
  5. 确认分片分配状态
    curl -X GET "localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason"
    
  6. 检查路径配置:确认 elasticsearch.ymlpath.data 配置正确且目录存在。

排查时需要注意的问题 #

  • 不要只看单个分片报错,要确认是单节点问题还是多节点共性问题。
  • 如果磁盘空间接近 100%,即使 store.createEmpty() 失败,也要先清理空间再重试。
  • 注意区分是 IOException(磁盘/权限)还是 EngineException(引擎层),两者的排查方向不同。

4. 如何解决这个错误 #

常用修复思路 #

  • 修复目录权限:确保数据目录属主正确,权限至少 755(目录)和 644(文件)。
    chown -R elasticsearch:elasticsearch /path/to/data
    chmod -R 755 /path/to/data
    
  • 清理磁盘空间:删除不必要的文件、旧日志或过期快照,确保磁盘使用率低于 85%。
  • 修复只读文件系统:如果是磁盘故障导致只读挂载,需要修复文件系统后重新挂载为读写模式。
  • 重试分片分配:修复底层问题后,手动触发分片重试。
    curl -X POST "localhost:9200/_cluster/reroute?retry_failed=true"
    
  • 清理残留目录:如果某个分片目录处于半初始化状态,可以停止节点后删除该分片目录,再重启让集群重新分配。
  • 调整恢复并发:如果并发恢复导致问题,可以临时降低恢复并发数。
    curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d '{
      "persistent": {
        "cluster.routing.allocation.node_concurrent_recoveries": 2
      }
    }'
    

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

  • 为磁盘空间设置告警阈值(如 80%、85%、90%),提前介入避免恢复失败。
  • 定期检查数据目录权限和磁盘健康状态,尤其是在节点迁移或磁盘更换后。
  • 对于关键索引,建议配置副本分片,避免单点存储问题导致数据不可用。
  • 使用 path.data 多路径配置时,确保每个路径都有足够的空间和正确的权限。

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

  • INFINI Console 适合查看集群健康度、节点磁盘使用率、分片分配状态和恢复进度,帮助快速判断异常是局部问题还是系统性问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测和流量治理,减少异常恢复期间对集群的额外压力。
  • 建议把磁盘、inode、文件系统错误和分片恢复失败事件统一接入监控面板,缩短从"发现问题"到"定位根因"的时间。

5. 小结 #

failed to create empty store 的核心问题是"空存储没有创建成功"。只要 store.createEmpty() 走不通,后续恢复就不可能成功。排查要优先落在节点本地存储环境:权限、磁盘空间、文件系统状态和 inode 使用率。

修复后通过 _cluster/reroute?retry_failed=true 触发分片重新分配,大多数情况下可以恢复正常。如果问题反复出现,需要从硬件、监控和集群配置三个层面进行系统性优化。

相关错误 #

附:日志上下文 #

private static void createEmptyStore(Store store) {
    store.incRef();
    try {
        store.createEmpty();
    } catch (final EngineException | IOException e) {
        throw new IndexShardRecoveryException(store.shardId(), "failed to create empty store", e);
    } finally {
        store.decRef();
    }
}