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

为什么这个错误发生 #

primary_missing_action_exception 表示在执行操作时找不到主分片。这通常发生在尝试对分片执行写入或更新操作时,主分片不可用或不存在。

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

  1. 主分片未分配:主分片未被分配到任何节点
  2. 主分片正在迁移:主分片正在迁移到另一个节点
  3. 主分片故障:主分片所在的节点发生故障
  4. 分片恢复中:主分片正在恢复过程中
  5. 节点离线:承载主分片的节点离线
  6. 集群状态不一致:集群状态出现不一致
  7. 分片被删除:主分片被删除但操作仍尝试访问
  8. 并发操作冲突:并发操作导致主分片状态混乱

如何修复这个错误 #

1. 检查分片状态 #

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

# 查看未分配的分片
GET /_cat/shards?v | grep UNASSIGNED

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

2. 查看集群健康状态 #

# 查看集群健康
GET /_cluster/health?v

# 等待集群恢复
GET /_cluster/health?wait_for_status=yellow&timeout=50s

3. 检查主分片分配 #

# 查看分配失败原因
GET /_cluster/allocation/explain?pretty

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

4. 触发分片重新分配 #

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

# 手动分配主分片(如果数据可以丢失)
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>",
        "accept_data_loss": true
      }
    }
  ]
}

5. 重启节点 #

# 如果承载主分片的节点有问题,重启该节点
sudo systemctl restart easysearch

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

6. 从副本提升 #

# 如果有可用的副本,可以将其提升为主分片
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<replica_node_name>",
        "accept_data_loss": false
      }
    }
  ]
}

7. 等待恢复完成 #

# 如果主分片正在恢复,等待恢复完成
GET /_cat/recovery?v&active_only=true

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

8. 检查节点状态 #

# 确保所有节点在线
GET /_cat/nodes?v&h=name,status

# 查看节点资源使用
GET /_cat/nodes?v&h=name,heap.percent,cpu,load_1m

9. 修复网络问题 #

# 测试节点间网络连接
ping <node_host>
telnet <node_host> 9300

# 检查防火墙规则
sudo iptables -L -n | grep 9300

10. 重置分配配置 #

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

11. 从快照恢复 #

# 如果主分片数据丢失,从快照恢复
POST /_snapshot/<repository>/<snapshot_name>/_restore
{
  "indices": "<index>",
  "include_global_state": false
}

12. 重建索引 #

# 如果无法恢复,可能需要重建索引
DELETE /<index>

# 重新创建索引并导入数据
PUT /<index>

13. 查看错误日志 #

# 查看主分片相关错误日志
grep -i "primary.*missing\|shard.*not.*found" /path/to/easysearch/logs/easysearch.log | tail -100

# 查看分配相关错误
grep -i "allocation.*fail" /path/to/easysearch/logs/easysearch.log | tail -50

14. 增加重试次数 #

# 如果是临时性问题,重试操作可能成功
# 在客户端实现重试机制

15. 配置副本 #

# 确保有足够的副本以避免数据丢失
PUT /<index>/_settings
{
  "index": {
    "number_of_replicas": 1
  }
}

预防措施 #

  • 配置足够的副本数
  • 监控分片分配状态
  • 保持节点健康运行
  • 定期创建快照备份
  • 实现客户端重试机制
  • 优雅关闭节点
  • 监控集群健康状态
  • 避免同时重启多个节点
  • 使用滚动重启
  • 配置合理的超时时间