Elasticsearch 7.17定时出现search_phase_execution_exception全分片失败求助
分析Elasticsearch
search_phase_execution_exception(全分片失败)的思路 问题场景
我们有一个3节点Elasticsearch集群:
- 数据量3.4G,总文档数23,478,158
- 索引动态更新,已删除文档数2,957,425
- 使用Java客户端提供服务端点,其中一个端点被消费者持续调用做数据验证(对比自身数据与主库)
- 请求传入ES的参数为3~10个,DSL中设置
withSize(5),包含nested query且配置ignoreUnmapped(true),无排序字段 - 每十分钟会触发
search_phase_execution_exception: all shards failed异常,异常源自RestClientTransport:310,已记录报错请求参数但无法复现,怀疑是缓存填满导致
异常堆栈:
co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/search] failed: [search_phase_execution_exception] all shards failed at co.elastic.clients.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:313) at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:153) at co.elastic.clients.elasticsearch.ElasticsearchClient.search(ElasticsearchClient.java:1754)
分析思路
一、集群基础状态排查
- 检查异常时段的集群健康:调用
_cluster/health,确认是否存在分片未分配、节点离线、集群状态变黄/红。全分片失败可能是节点临时离线导致对应分片无响应。 - 监控节点资源:查看异常时段的CPU、堆内存、磁盘IO指标(可通过
_cat/nodes?v或内部监控工具),确认是否出现CPU飙升(如GC过载)、堆内存耗尽、磁盘读写超时。 - 分片与碎片整理:已删除文档占总文档数约12%,可手动触发分片合并(
POST /_forcemerge?max_num_segments=1),减少磁盘碎片与内存占用;同时检查分片数设置是否合理,3节点集群分片过多会加重单节点负载。
二、缓存相关验证(针对你的怀疑)
- 查询缓存(Query Cache):查看
_cat/nodes?v中的query_cache_memory_size、query_cache_hit_rate,确认异常时段是否出现缓存命中率骤降、内存占用达上限。也可通过_indices/stats?pretty查看具体索引的查询缓存详情。 - 字段数据缓存(Field Data Cache):nested query可能加载嵌套字段的字段数据,查看
fielddata_memory_size是否过高,若内存占用超标会触发堆内存压力。可限制缓存大小(indices.fielddata.cache.size: 20%)或改用doc values(字段支持的前提下)。 - 请求缓存(Request Cache):虽当前查询size=5用不上聚合,但仍可检查
request_cache_memory_size是否有异常波动。
三、查询与客户端层面排查
- 查询执行计划分析:用
_validate/query?explain解析nested query的执行逻辑,确认ignoreUnmapped(true)是否生效,是否因请求参数中大量不同嵌套字段导致解析开销过高。 - 客户端连接池配置:检查Java客户端的
max_conns_per_route、max_total_conns参数,若连接池耗尽会导致请求排队超时,进而触发全分片失败。查看客户端日志是否有连接超时、拒绝的记录。 - 请求量时间分布:统计异常时段的请求量,确认是否存在每十分钟的请求峰值(如消费者定时批量触发),导致集群过载。
四、日志深度分析
- ES慢查询日志:开启慢查询日志(如设置
index.search.slowlog.threshold.query.warn: 1s),捕获异常时段的慢查询,查看是否有执行时间过长导致超时或分片失败。 - ES节点错误日志:查看
elasticsearch.log中异常时段的详细报错,比如是否是circuit_breaking_exception(熔断)、out_of_memory_error或shard_timeout_exception,这些细节可直接定位根因。 - Java客户端日志:除堆栈外,检查是否有连接超时、SocketException等底层错误,这类错误通常是集群节点不可达的信号。
五、临时验证方案
- 调整缓存配置:临时增大查询缓存内存(
indices.queries.cache.size: 20%,默认10%)或针对该索引禁用查询缓存(index.queries.cache.enabled: false),观察异常是否消失。 - 优化nested查询:若嵌套结构复杂,考虑将嵌套字段扁平化,减少nested query的执行开销;确认
ignoreUnmapped确实过滤了未映射字段,避免无效查找。 - 临时扩容资源:若确认是内存或CPU瓶颈,临时增加节点堆内存(注意不超过32G)或CPU资源,验证是否缓解问题。
内容的提问来源于stack exchange,提问作者Ronny
相关产品推荐
相关产品推荐

