为什么这个错误发生 #
primary_missing_action_exception 表示在执行操作时找不到主分片。这通常发生在尝试对分片执行写入或更新操作时,主分片不可用或不存在。
这个错误可能由以下原因引起:
- 主分片未分配:主分片未被分配到任何节点
- 主分片正在迁移:主分片正在迁移到另一个节点
- 主分片故障:主分片所在的节点发生故障
- 分片恢复中:主分片正在恢复过程中
- 节点离线:承载主分片的节点离线
- 集群状态不一致:集群状态出现不一致
- 分片被删除:主分片被删除但操作仍尝试访问
- 并发操作冲突:并发操作导致主分片状态混乱
如何修复这个错误 #
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
}
}
预防措施 #
- 配置足够的副本数
- 监控分片分配状态
- 保持节点健康运行
- 定期创建快照备份
- 实现客户端重试机制
- 优雅关闭节点
- 监控集群健康状态
- 避免同时重启多个节点
- 使用滚动重启
- 配置合理的超时时间





