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

为什么这个错误发生 #

shard_not_in_primary_mode_exception 表示分片当前不处于主模式(primary mode),但操作要求分片必须是主分片。这通常发生在尝试对副本分片执行只有主分片才能执行的操作时。

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

  1. 分片是副本:操作针对的是副本分片而非主分片
  2. 主分片迁移中:主分片正在迁移到其他节点
  3. 分片恢复中:分片正在恢复过程中
  4. 分片状态转换:分片正在进行状态转换
  5. 主分片故障:主分片故障,副本尚未提升
  6. 并发操作冲突:并发操作导致分片状态混乱
  7. 节点角色变化:节点角色从主节点变为副本节点

如何修复这个错误 #

1. 检查分片状态 #

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

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

2. 定位主分片 #

# 找到主分片所在节点
GET /_cat/shards?v&h=index,shard,prirep,state,node | grep "<index>" | grep "p"

# 或使用
GET /_cluster/state?filter_path=**.routing_table

3. 对主分片执行操作 #

# 确保操作针对主分片而非副本
# 在 API 请求中指定偏好
GET /<index>/_search?preference=_primary

4. 等待主分片恢复 #

# 如果主分片故障,等待其恢复或副本提升
GET /_cat/shards?v&h=index,shard,prirep,state

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

5. 手动提升副本为主分片 #

# 如果主分片永久丢失,可以强制提升副本
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "<index>",
        "shard": 0,
        "node": "<replica_node_name>",
        "accept_data_loss": true
      }
    }
  ]
}

6. 等待分片迁移完成 #

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

# 查看迁移进度
GET /_cluster/allocation/explain?pretty

7. 检查节点状态 #

# 确保承载主分片的节点在线
GET /_cat/nodes?v&h=name,status

# 查看节点详细信息
GET /_nodes

8. 重启节点 #

# 如果节点状态异常,重启该节点
sudo systemctl restart easysearch

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

9. 重新分配分片 #

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

# 手动分配
POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_replica": {
        "index": "<index>",
        "shard": 0,
        "node": "<node_name>"
      }
    }
  ]
}

10. 查看错误日志 #

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

# 查看分片相关错误
grep -i "shard.*error\|primary.*fail" /path/to/easysearch/logs/easysearch.log | tail -50

11. 检查集群状态 #

# 确保集群状态正常
GET /_cluster/health?v

# 查看集群状态详情
GET /_cluster/state?filter_path=**.routing_table

12. 验证索引配置 #

# 检查索引的副本配置
GET /<index>/_settings?filter_path=**.number_of_replicas

# 确保有足够的副本

13. 处理并发操作 #

# 如果是并发操作导致的问题,减少并发
# 或实现操作队列

14. 从快照恢复 #

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

15. 等待分片初始化 #

# 如果分片正在初始化,等待初始化完成
GET /_cat/shards?v&h=index,shard,prirep,state,init_phase

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

预防措施 #

  • 配置足够的副本数
  • 监控主分片健康状态
  • 实现故障自动转移
  • 优雅关闭节点
  • 使用滚动重启
  • 监控集群健康状态
  • 实现客户端重试
  • 处理分片状态转换
  • 监控分片分配
  • 使用快照备份