为什么这个错误发生 #
shard_not_in_primary_mode_exception 表示分片当前不处于主模式(primary mode),但操作要求分片必须是主分片。这通常发生在尝试对副本分片执行只有主分片才能执行的操作时。
这个错误可能由以下原因引起:
- 分片是副本:操作针对的是副本分片而非主分片
- 主分片迁移中:主分片正在迁移到其他节点
- 分片恢复中:分片正在恢复过程中
- 分片状态转换:分片正在进行状态转换
- 主分片故障:主分片故障,副本尚未提升
- 并发操作冲突:并发操作导致分片状态混乱
- 节点角色变化:节点角色从主节点变为副本节点
如何修复这个错误 #
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
预防措施 #
- 配置足够的副本数
- 监控主分片健康状态
- 实现故障自动转移
- 优雅关闭节点
- 使用滚动重启
- 监控集群健康状态
- 实现客户端重试
- 处理分片状态转换
- 监控分片分配
- 使用快照备份





