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

为什么这个错误发生 #

shard_not_found_exception 表示尝试访问的分片不存在。分片是索引的水平分割单元,当分片不存在时会发生此错误。

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

  1. 分片 ID 错误:请求中指定的分片 ID 不正确
  2. 分片未分配:分片已创建但未分配到任何节点
  3. 分片已被删除:分片所属的索引被删除或修改
  4. 分片正在迁移:分片正在从一个节点迁移到另一个节点
  5. 分片状态异常:分片处于初始化或恢复状态
  6. 索引正在创建:索引刚创建,分片尚未完全初始化
  7. 路由计算错误:文档路由到不存在的分片
  8. 集群分裂:网络分区导致分片不可访问

如何修复这个错误 #

1. 检查分片状态 #

# 查看索引的所有分片
GET /_cat/shards/<index>?v

# 查看特定分片的状态
GET /_cat/shards/<index>?v&h=index,shard,prirep,state,unassigned.reason

2. 查看未分配的分片 #

# 解释为什么分片未分配
GET /_cluster/allocation/explain

# 查看特定分片
GET /_cluster/allocation/explain
{
  "index": "<index>",
  "shard": 0,
  "primary": true
}

3. 触发分片分配 #

# 重试失败的分配
POST /_cluster/reroute?retry_failed=true

# 手动分配分片到特定节点
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>",
        "accept_data_loss": true
      }
    }
  ]
}

4. 检查索引配置 #

# 查看索引的分片配置
GET /<index>/_settings?flat_settings=true

# 检查分片数量
GET /<index>/_settings/index.number_of_shards

5. 等待分片初始化 #

# 等待所有分片分配完成
GET /_cluster/health?wait_for_no_initializing_shards=true&timeout=50s

# 等待索引达到绿色状态
GET /_cluster/health/<index>?wait_for_status=green&timeout=50s

6. 修复分片分配问题 #

# 检查分配设置
GET /_cluster/settings?flat_settings=true

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

7. 处理数据丢失情况 #

如果主分片丢失且无法恢复:

# 分配过时的主分片(会丢失数据)
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_empty_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>",
        "accept_data_loss": true
      }
    }
  ]
}

8. 使用路由 #

# 使用路由确保文档在同一分片上
POST /<index>/_doc/<id>?routing=<user_id>
{
  "field": "value"
}

# 查询时使用路由
GET /<index>/_search?routing=<user_id>
{
  "query": {
    "match_all": {}
  }
}

9. 重建索引 #

如果分片无法恢复:

# 重建索引(重新分配分片)
POST /<index>/_split/<new-index>?wait_for_active_shards=all
{
  "settings": {
    "index.number_of_shards": 6
  }
}

# 或使用 shrink 减少分片
POST /<index>/_shrink/<new-index>?wait_for_active_shards=all
{
  "settings": {
    "index.number_of_shards": 1,
    "index.number_of_replicas": 0
  }
}

10. 检查节点状态 #

# 查看节点状态
GET /_cat/nodes?v

# 确保有足够的节点容纳所有分片

预防措施 #

  • 合理规划分片数量,避免过多或过少
  • 确保有足够的节点来容纳所有主分片和副本分片
  • 使用副本提高数据可用性
  • 监控分片状态,及时发现未分配的分片
  • 配置合理的分片分配规则
  • 在节点下线前正确移除节点
  • 使用集群健康监控及时发现问题
  • 对于关键数据,配置多个副本