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

为什么这个错误发生 #

no_longer_primary_shard_exception 表示当前节点上的分片不再是主分片。这是因为主分片已经转移到其他节点,当前分片已降级为副本或被标记为过期。

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

  1. 主分片转移:主分片已迁移到其他节点
  2. 主分片切换:原主分片故障,新的主分片已被选出
  3. 主分片降级:当前分片被标记为过期(stale),不再是主分片
  4. Primary Term 不匹配:操作的 Primary Term 与当前集群状态不匹配
  5. 网络分区:网络分区导致脑裂,当前分片失去主分片地位
  6. 并发操作冲突:其他操作导致主分片转移
  7. 节点恢复:原故障节点恢复后,其上的分片不再是主分片

如何修复这个错误 #

1. 检查分片状态和主分片位置 #

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

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

2. 重新执行操作 #

主分片转移后,需要向新的主分片重新发送请求:

# 客户端通常会自动重试,或手动重试
POST /<index>/_doc/<id>
{
  "field": "value"
}

3. 等待集群稳定 #

# 等待主分片选举完成
GET /_cluster/health?wait_for_status=yellow&timeout=50s

# 查看主分片信息
GET /_cat/master?v

4. 使用一致性写入 #

# 确保写入操作有足够的确认
POST /<index>/_doc/<id>?wait_for_active_shards=quorum
{
  "field": "value"
}

# 或等待所有副本
POST /<index>/_doc/<id>?wait_for_active_shards=all
{
  "field": "value"
}

5. 检查 Primary Term #

# 如果使用条件更新,检查 Primary Term 是否匹配
POST /<index>/_update/<id>
{
  "doc": {
    "field": "value"
  },
  "if_primary_term": 1  # 需要与当前 Primary Term 匹配
}

6. 查看集群状态变更 #

# 查看最近的集群状态变更
GET /_cluster/state?filter_path=**.metadata.**.primary_term

# 查看分片历史状态
GET /<index>/_explain?pretty

7. 检查节点日志 #

# 查看主分片转移相关日志
grep -i "primary" /path/to/easysearch/logs/easysearch.log | tail -100

# 查看分片状态变更
grep -i "shard.*state" /path/to/easysearch/logs/easysearch.log | tail -100

8. 处理脑裂情况 #

如果怀疑发生脑裂:

# 检查集群状态
GET /_cluster/state?filter_path=**.nodes,**.master_node

# 重启受影响的节点以恢复集群一致性

9. 使用乐观并发控制 #

# 使用序列号和 Primary Term 进行条件更新
POST /<index>/_update/<id>
{
  "doc": {
    "field": "value"
  },
  "if_seq_no": 5,
  "if_primary_term": 1
}

10. 配置合理的超时和重试 #

# Python 客户端配置
from elasticsearch import Elasticsearch

es = Elasticsearch(
    ["http://node1:9200", "http://node2:9200"],
    max_retries=3,
    retry_on_timeout=True,
    # 自动发现主节点变化
    sniff_on_start=True,
    sniff_on_connection_fail=True
)

预防措施 #

  • 配置足够的候选主节点防止脑裂
  • 使用法定人数机制
  • 监控主分片状态
  • 实现客户端自动重试和主节点发现
  • 避免网络分区
  • 使用稳定可靠的硬件和网络
  • 配置合理的超时时间
  • 监控集群健康状态
  • 对于关键操作,使用一致性写入确保数据可靠性