从ElasticSearch 6.8拉取大批量数据时集群报内存溢出错误
问题定位
- ES 6.8默认配置下JVM堆内存仅分配
1GB,3节点承载3000万数据本身堆内存就长期处于高占用状态,没有给大查询预留足够的计算内存空间。 - 你大概率是用
from + size的普通分页逻辑拉取数据,触发了深分页OOM:ES普通分页需要协调节点把所有分片返回的from + size条结果全部加载到堆内存做全局排序,和你设置的pagesize=1000没有关系,当累计拉取到1000万条时,查询偏移量已经到1000万级别,单次要加载的待排序结果达到千万级,直接打满节点堆内存触发崩溃。 - 如果你已经用了scroll接口拉取数据,问题出在两个点:要么scroll超时时间设得太长,拉取过程中生成的scroll上下文持续占用堆内存没有及时释放,累计内存开销打满堆;要么拉取完成后没有主动清理scroll上下文,大量残留上下文占住内存不释放。
- 默认配置下ES的查询内存断路器阈值为堆内存的70%,但深分页、残留scroll上下文产生的内存开销很多时候不会被断路器准确统计,不会提前触发拦截,会直接导致真实OOM节点崩溃。
修复方案
- 先调整JVM基础配置:修改每个节点
config/jvm.options文件中的-Xms、-Xmx参数,两个值保持一致,设置为单节点物理内存的50%,最高不要超过32GB(比如单节点物理内存16G就设为8G,8G物理内存就设为4G),修改完成后滚动重启所有节点生效。 - 立刻停止用
from + size方式拉取超大数据集,按需选择以下两种深度拉取方案:- 有临时全量导出需求用scroll接口:scroll超时时间不要设太长,建议设为
1m(1分钟),每次请求带上上一次返回的scroll_id,每次请求会自动刷新scroll超时时间,全部数据拉取完成后必须主动调用清理接口删除对应scroll上下文,不要等超时自动释放。 - 有持续深度分页查询需求优先用
search_after:不需要维护常驻scroll上下文,内存开销比scroll低30%以上,每次查询传入上一页最后一条数据的排序字段值即可,不会触发千万级结果全局排序的内存开销。
- 有临时全量导出需求用scroll接口:scroll超时时间不要设太长,建议设为
- 调整断路器配置,在每个节点的
elasticsearch.yml中添加配置indices.breaker.total.limit: 80%,让查询阶段更早触发内存拦截,避免直接打满整个堆导致节点进程崩溃。 - 大结果集拉取任务不要高并发跑,单集群同时运行的千万级数据拉取任务不要超过2个,避免多个大查询同时抢占堆内存。
内容的提问来源于stack exchange,提问作者harryboot
相关产品推荐
相关产品推荐

