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%"
  }
}

可按需调小,缺点:超大查询会直接拒绝报错。

四、生产优化要点

  1. 关闭 swap:bootstrap.memory_lock: true,防止 ES 内存被交换到磁盘,GC 雪崩
    # elasticsearch.yml
    bootstrap.memory_lock: true
    

    需要操作系统修改 limits.conf,否则启动失败。

  2. 优化查询:
    • 分页用search_after替代大 from/size
    • text 字段聚合改成 keyword 子字段
    • 限制 terms 聚合 size,不要设超大值
  3. 索引侧:分片不要过多,单分片建议 20~40G;分片过多会加重堆压力。

posted on 2026-09-22 08:53  AI老炮  阅读(27)  评论(0)    收藏  举报