适用版本: 6.8-8.9
1. 错误异常的基本描述 #
failed to create empty store 出现在分片恢复(recovery)阶段。当 Elasticsearch 尝试为一个分片初始化空的底层存储目录时,如果 store.createEmpty() 调用失败,就会抛出 IndexShardRecoveryException。
这不是搜索请求错误,而是分片恢复或初始化底层目录失败,通常发生在以下场景:
- 新分片分配(primary 或 replica)
- 分片恢复(节点重启后、集群扩容、节点间分片迁移)
- 快照恢复(从快照还原索引时)
常见现象 #
- 分片状态长期处于
INITIALIZING或UNASSIGNED,无法完成恢复。 - 节点日志中反复出现
failed to create empty store异常,伴随IndexShardRecoveryException。 - 集群健康状态变为
yellow或red,受影响的索引分片无法上线。 - 有时还会伴随
IOException、AccessDeniedException或FileSystemException等底层异常。
典型报错与异常栈 #
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.yml中path.data配置的路径不存在或不可访问。 - 并发恢复冲突:多个分片同时恢复时,底层目录创建发生竞争或冲突。
- 残留文件干扰:之前异常中断的恢复留下了不完整或半初始化的目录结构。
3. 如何排查这个异常 #
建议按以下顺序进行排查:
- 检查节点日志:在报错节点上查看 Elasticsearch 日志,确认完整的异常栈和
Caused by信息,定位是权限、磁盘还是 I/O 问题。 - 检查数据目录权限:确认
path.data目录的属主和权限,Elasticsearch 进程用户必须有读写执行权限。ls -la /path/to/elasticsearch/data/ - 检查磁盘空间和使用率:
df -h df -i # 检查 inode 使用情况 - 检查文件系统状态:确认磁盘没有被挂载为只读。
mount | grep <disk> dmesg | tail -50 # 查看是否有磁盘 I/O 错误 - 确认分片分配状态:
curl -X GET "localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason" - 检查路径配置:确认
elasticsearch.yml中path.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();
}
}





