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

为什么这个错误发生 #

index_shard_recovering_exception 表示尝试对正在进行恢复(recovering)的分片执行不允许的操作。当分片处于恢复状态时,某些操作(如再次启动恢复)会被拒绝。

这个错误可能由以下原因引起:

  1. 分片正在恢复:分片当前正在执行恢复操作
  2. 并发恢复请求:同时发起了多个恢复请求
  3. 分片处于恢复后状态:分片处于 POST_RECOVERY 状态
  4. 节点重启后:节点重启后分片正在进行恢复
  5. 副本恢复:副本分片正在从主分片恢复数据
  6. 快照恢复:从快照恢复分片时发生
  7. ** relocation 过程**:分片正在迁移到另一个节点
  8. 恢复未完成:之前的恢复操作尚未完成

如何修复这个错误 #

1. 检查分片状态 #

# 查看分片当前状态
GET /_cat/shards?v&h=index,shard,prirep,state,node

# 查看特定索引的分片状态
GET /<index>/_shard_stores?status=recovering

# 查看分片恢复状态
GET /<index>/_recovery?active_only=true

2. 等待恢复完成 #

# 等待当前恢复操作完成
GET /_cat/recovery?v

# 查看恢复进度
GET /_cat/recovery?v&h=index,shard,bytes,bytes_pct,stage

# 等待集群状态变为绿色
GET /_cluster/health?wait_for_status=green&timeout=300s

3. 取消恢复(如果卡住) #

# 如果恢复卡住,可以尝试取消并重新分配
POST /_cluster/reroute
{
  "commands": [
    {
      "cancel": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>"
      }
    }
  ]
}

# 然后重新分配
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_replica": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>"
      }
    }
  ]
}

4. 强制分配分片 #

# 如果恢复失败,可以尝试强制分配
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>",
        "accept_data_loss": true
      }
    }
  ]
}

5. 从快照恢复 #

# 如果恢复失败,可以从快照重新恢复
POST /_snapshot/<repository>/<snapshot_name>/_restore
{
  "indices": "<index>",
  "include_global_state": false
}

# 查看可用的快照
GET /_snapshot/<repository>/_all

6. 重启节点 #

# 在承载问题分片的节点上重启服务
sudo systemctl restart easysearch

# 等待节点加入集群
GET /_cat/nodes?v

7. 删除并重建索引 #

# 如果没有重要数据,可以删除并重建索引
DELETE /<index>

# 重新创建索引
PUT /<index>

# 从数据源重新导入数据

8. 检查恢复配置 #

# 在 easysearch.yml 中调整恢复配置
cluster.routing.allocation.node_initial_primaries_recoveries: 4
cluster.routing.allocation.node_concurrent_recoveries: 2
indices.recovery.max_bytes_per_sec: 50mb

9. 查看恢复详情 #

# 查看详细的恢复信息
GET /<index>/_recovery?active_only=true&detailed=true

# 查看所有分片的恢复状态
GET /_recovery?human&detailed=true

10. 检查磁盘空间 #

# 确保有足够的磁盘空间进行恢复
GET /_cat/allocation?v

# 查看磁盘使用
df -h /path/to/easysearch/data

11. 增加恢复并发数 #

# 如果有很多分片需要恢复,可以增加并发数
PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.node_concurrent_recoveries": 6,
    "cluster.routing.allocation.node_initial_primaries_recoveries": 8
  }
}

12. 限制恢复带宽 #

# 避免恢复占用过多带宽
PUT /<index>/_settings
{
  "index": {
    "recovery": {
      "max_bytes_per_sec": "20mb"
    }
  }
}

13. 检查节点日志 #

# 查看恢复相关错误日志
grep -i "recover\|restore" /path/to/easysearch/logs/easysearch.log | tail -100

# 查看分片相关日志
grep -i "shard.*error" /path/to/easysearch/logs/easysearch.log | tail -50

14. 重置分片分配 #

# 重新启用分片分配
PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.enable": "all"
  }
}

# 触发重新分配
POST /_cluster/reroute?retry_failed=true

预防措施 #

  • 优雅关闭节点(避免强制终止)
  • 保持足够的磁盘空间
  • 配置合理的恢复速度限制
  • 监控恢复进度
  • 使用快照备份重要数据
  • 避免频繁的分片迁移
  • 配置足够的副本数
  • 监控集群健康状态
  • 在低峰期执行节点维护
  • 使用滚动重启而非同时重启多个节点