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

适用版本: 6.8-8.9

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

failed to load started shards 出现在节点 gateway 读取本地分片状态的流程里。源码在返回 NodeGatewayStartedShards 前捕获通用异常并抛出当前错误,因此问题通常与节点本地 shard state 文件、分片目录或恢复状态有关,而不是普通网络请求失败。

这不是"分片还没启动",而是"本地已启动分片状态读不出来"。

常见现象 #

  • 节点启动后,分片分配或主副本恢复异常,分片可能长时间处于 INITIALIZINGUNASSIGNED 状态。
  • 集群请求节点上报 started shards 信息时失败,导致恢复判断不完整。
  • 某个节点反复报错,而同一索引在其他节点可能正常。
  • 在 Kibana 的集群健康界面中,可能看到分片分配失败或恢复停滞。
  • Elasticsearch 日志中可以看到 failed to load started shards 关键字,伴随 IOException 或状态解析异常。

典型报错与异常栈 #

常见日志形态通常类似下面这样:

ElasticsearchException: failed to load started shards
Caused by: java.io.FileNotFoundException: /path/to/elasticsearch/data/nodes/0/indices/{index_uuid}/{shard_id}/state
	at java.io.FileInputStream.open0(Native Method)

或者状态文件损坏:

ElasticsearchException: failed to load started shards
Caused by: java.io.IOException: Unexpected end of file
	at org.elasticsearch.common.xcontent.XContentHelper...

或者磁盘 I/O 错误:

ElasticsearchException: failed to load started shards
Caused by: java.io.IOException: Input/output error
	at java.io.FileInputStream.readBytes(Native Method)

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

failed to load started shards 的根因是"本地已启动分片状态不可读"。Elasticsearch 在节点启动时需要从本地磁盘读取分片状态信息(shard_state 文件),以确定哪些分片已经启动;如果状态文件有问题,就会导致此异常。

常见原因通常包括:

  • 本地分片 state 文件问题:本地分片 state 文件缺失、损坏或格式异常(如 state-*.st 文件)。
  • 磁盘或文件系统问题:节点磁盘、挂载目录或文件系统出现问题,导致读取中断。
  • 残留不完整数据:节点上残留不完整的 shard 数据目录,例如异常重启或手工清理后留下半成品。
  • 升级或迁移遗留问题:升级、迁移或恢复过程中,本地 shard metadata 与集群视图不一致。
  • 异常重启或强制终止:Elasticsearch 进程被强制 kill(kill -9),导致状态文件写入不完整。
  • 手工目录操作:手工修改分片目录(如直接删除文件),导致状态信息不一致。
  • 磁盘空间不足:磁盘空间不足导致状态文件无法正确写入或读取。
  • 文件权限问题:Elasticsearch 用户没有读取分片状态文件的权限。

3. 如何排查和解决这个异常和解决这个异常 #

建议按"先检查节点本地目录、再检查磁盘健康、后修复分片状态"的顺序处理:

  1. 检查报错节点的本地分片目录:在报错节点上检查对应索引和分片目录是否完整,确认 state 文件存在。

    # 查看节点本地分片目录
    ls -la /path/to/elasticsearch/data/nodes/0/indices/
       
    # 查看特定索引的分片目录
    ls -la /path/to/elasticsearch/data/nodes/0/indices/{index_uuid}/
       
    # 检查 state 文件是否存在
    find /path/to/elasticsearch/data/nodes/0/indices/ -name "state*"
    
  2. 查看节点日志和系统日志:查看节点日志与系统日志,检查磁盘 I/O、文件系统和挂载异常。

    # 查看 Elasticsearch 日志
    grep -r "failed to load started shards" /var/log/elasticsearch/
    grep -r "IOException\|state" /var/log/elasticsearch/ | tail -50
       
    # 查看系统日志中的磁盘错误
    dmesg | grep -i "error\|io\|ext4\|xfs"
       
    # 检查磁盘空间
    df -h
    
  3. 对比主副本节点:对比主副本节点的本地目录,判断是否只有单节点数据损坏。

    # 查看分片分配
    curl -X GET "localhost:9200/_cat/shards/my_index?v"
       
    # 查看分片分配解释
    curl -X GET "localhost:9200/_cluster/allocation/explain?pretty"
    
  4. 检查分片历史操作:检查该分片最近是否经历了异常重启、迁移中断或手工目录操作。

    # 查看 Elasticsearch 日志中的分片相关记录
    grep -r "shard.*my_index\|recovery.*my_index" /var/log/elasticsearch/ | tail -100
    
  5. 检查健康副本:如有健康副本,优先考虑从副本恢复,而不是在损坏目录上反复重试。

    # 查看索引的健康副本
    curl -X GET "localhost:9200/_cat/shards/my_index?v&h=index,shard,prirep,state,node"
    

排查时需要注意的问题 #

  • 这个错误是本地分片状态问题,不是集群状态或分片分配策略问题,需要重点关注节点本地存储,而不是集群层面的设置。
  • 如果问题只在某些节点上出现,很可能是节点本地状态文件的问题,需要检查节点间的状态一致性。
  • 手工修改分片目录(如在数据目录下直接删除文件)是高风险操作,容易导致状态不一致。

4. 如何解决这个错误 #

常用修复思路 #

  • 修复节点磁盘或挂载问题:修复节点磁盘或挂载问题,确保本地 shard state 可以稳定读取。

    # 检查并修复文件系统(需要停机操作)
    fsck /dev/sdX
      
    # 检查文件句柄使用
    lsof -p $(pgrep -f elasticsearch) | wc -l
    
  • 清理并恢复损坏的分片目录:对损坏的本地分片目录执行安全清理,再由集群从健康副本重新分配。

    # 停止 Elasticsearch 节点
    systemctl stop elasticsearch
      
    # 备份并清理损坏的分片目录(谨慎操作)
    mv /path/to/elasticsearch/data/nodes/0/indices/{index_uuid}/{shard_id} /tmp/shard_backup
      
    # 重启节点,让集群从副本恢复
    systemctl start elasticsearch
    
  • 从健康副本恢复:恢复或重建异常分片,避免继续依赖不完整的本地状态。

    # 尝试分配副本分片
    curl -X POST "localhost:9200/_cluster/reroute" -H 'Content-Type: application/json' -d'
    {
      "commands": [
        {
          "allocate_replica": {
            "index": "my_index",
            "shard": 0,
            "node": "target_node_name"
          }
        }
      ]
    }
    '
    
  • 重建索引:如果多个分片都有问题,考虑重建整个索引。

    # 重建索引
    curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
    {
      "source": { "index": "old_index" },
      "dest": { "index": "new_index" }
    }
    '
    
  • 加强节点运维规范:避免手工修改分片目录或在恢复期间强制中断。

    # 正确停止 Elasticsearch 节点(不要使用 kill -9)
    systemctl stop elasticsearch
    # 或者使用 API
    curl -X POST "localhost:9200/_cluster/nodes/{node_id}/_shutdown"
    

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

  • 建立节点本地状态的监控,定期检查分片目录的完整性和健康度。
  • 避免手工修改数据目录,所有分片操作都应通过 Elasticsearch API 完成。
  • 在升级 Elasticsearch 版本前,仔细阅读升级说明,必要时先备份数据。
  • 为节点磁盘空间、I/O 等待和文件系统错误配置监控和告警,在问题影响分片状态前及时通知。
  • 对于重要索引,配置至少 1 个副本分片,确保在主分片本地状态损坏时可以快速恢复。

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

  • INFINI Console 适合查看集群的分片状态、节点存储、恢复进度和错误趋势,帮助快速定位 failed to load started shards 是本地状态问题、磁盘问题还是恢复不一致问题,并提供可视化的分片管理和修复操作。
  • INFINI Gateway 可以记录所有恢复相关的请求日志,帮助定位分片恢复失败的具体环节,同时提供请求审计功能。
  • 建议将分片状态、恢复成功率、磁盘健康度和节点错误统一接入监控面板,结合 INFINI Console 的告警功能,在分片状态加载失败时及时通知管理员。

5. 小结 #

failed to load started shards 的关键是"本地已启动分片状态不可读"。排查重点应放在节点本地磁盘、分片目录和 shard state 文件健康度,而不是只看分配结果表面现象。大多数情况下,这个问题可以通过修复磁盘问题、清理损坏目录和从健康副本恢复来解决。

只要把节点本地状态监控、磁盘健康管理和恢复策略固定下来,大多数分片状态加载类异常都可以被有效预防,也更容易通过 INFINI Console 和 INFINI Gateway 实现持续防护。

相关错误 #

参考文档 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

return new NodeGatewayStartedShards(clusterService.localNode(), allocationId, shardStateMetadata.primary);
}
logger.trace("{} no local shard info found", shardId);
return new NodeGatewayStartedShards(clusterService.localNode(), null, false);
} catch (Exception e) {
    throw new ElasticsearchException("failed to load started shards", e);
}