ES java.lang.OutOfMemoryError: Java heap space
含义:JVM 堆内存耗尽,ES 节点直接 OOM 崩溃退出。
核心规则:
-Xms和-Xmx必须相等;最大不超过31G;建议设为服务器物理内存的 50%,留一半给系统文件缓存(ES 非常依赖)Elastic
一、修改 JVM 堆内存(最常用方案)
配置文件:config/jvm.options
# 修改这两行,示例:服务器内存16G,分配8G给ES
-Xms8g
-Xmx8g
❌ 不要超过 31G,超过后压缩指针失效,内存利用率反而变差。
修改后重启 ES 节点生效。
Docker 环境:使用环境变量
-e ES_JAVA_OPTS="-Xms8g -Xmx8g"
二、先排查:是堆太小,还是查询打爆内存
1. 查看堆使用(Kibana 开发工具)
GET _nodes/stats/jvm?pretty
看 heap_used_percent,持续长期 85% 以上就是堆不足。
2. 常见打爆堆的 SQL / 查询
- 超大聚合、
terms无 size 限制、深度分页from+size很大 - 对 text 字段做排序 / 聚合(加载大量 fielddata)
- 一次性大批量导入数据,bulk 太大
临时清理 fielddata 缓存
POST _cache/clear?fielddata=true
三、熔断保护(防止单条大查询直接 OOM)
动态调整,无需重启:
# 设置熔断,限制查询最多占用堆的40%
PUT _cluster/settings
{
"persistent": {
"indices.breaker.total.limit": "40%"
}
}
可按需调小,缺点:超大查询会直接拒绝报错。
四、生产优化要点
- 关闭 swap:
bootstrap.memory_lock: true,防止 ES 内存被交换到磁盘,GC 雪崩# elasticsearch.yml bootstrap.memory_lock: true需要操作系统修改 limits.conf,否则启动失败。
- 优化查询:
- 分页用
search_after替代大 from/size - text 字段聚合改成 keyword 子字段
- 限制 terms 聚合 size,不要设超大值
- 分页用
- 索引侧:分片不要过多,单分片建议 20~40G;分片过多会加重堆压力。
浙公网安备 33010602011771号