Elasticsearch内存管理与JVM优化:原理剖析与最佳实践

news2025/5/13 17:47:01

#作者:孙德新

文章目录

  • 一、Elasticsearch缓存分类
    • 1、Node Query Cache:
    • 2、Shard Request Cache:
    • 3、Fielddata Cache:
  • 三、内存常见的问题
    • 案例一
    • 案例二
    • 案例三
    • 案例四
  • 四、内参分配最佳实践
    • 1、jvm heap分配
    • 2、将机器上少于一半的内存分配给es
    • 3、不要给jvm分配超过32G内存
    • 4、在32G以内的话具体应该设置heap为多大?
    • 5、对于有1TB内存的超大内存机器该如何分配?
    • 6、swapping

一、Elasticsearch缓存分类

1、Node Query Cache:

每一个节点有一个 Node Query 缓存
由该节点的所有 Shard 共享,只缓存 Filter Context 相关内容
Cache 采用 LRU 算法
静态配置,需要设置在每个 Data Node 上
Node Level - indices.queries.cache.size:”10%”
Index Level: index.queries.cache.enabled: true

2、Shard Request Cache:

缓存每个分片上的查询结果
只会缓存设置了 size=0 的查询对应的结果。不会缓存hits。但是会缓存 Aggregations 和 Suggestions
Cache Key
LRU 算法,将整个 JSON 查询串作为 Key,与 JSON对象的顺序相关
静态配置
数据节点: indices.requests.cache.size:“1%

3、Fielddata Cache:

除了 Text 类型,默认都采用 doc_values。:节约了内存。Aggregation 的 Global ordinals 也保存在 Fielddata cache 中
Text 类型的字段需要打开 Fileddata 才能对其进行聚合和排序。Text 经过分词,排序和聚合效果不佳,建议不要轻易使用
配置:可以控制 Indicesfielddatacachesize 避免产生 GC(默认无限制)

缓存失效:
Node Query,Cache。保存的是 Segment 级缓存命中的结果。Segment 被合并后,缓存会失效
Shard Request Cache:分片 Refresh 时候,Shard Request Cache 会失效。如果 Shard 对应的数据频繁发生变化,该缓存的效率会很差
Fielddata Cache:segment被合并后会失效

二、管理内存的重要性:

  1. Elasticsearch 高效运维依赖于内存的合理分配。可用内存一半分配给 JVM,一半留给操作系统,缓存索引文件
  2. 内存问题,引发的问题
    长时间 GC,影响节点,导致集群响应缓慢
    OOM.导致丢节点

三、内存常见的问题

案例一

问题:Segments 个数过多,导致 full GC
现象: 集群整体响应缓慢,也没有特别多的数据读写。但是发现节点在持续进行 Full GC
分析: 查看 Elasticsearch 的内存使用,发现 segments.memory 占用很大空间
解决: 通过 force merge,把 segments 合并成一个
建议: 对于不在写入和更新的索引,可以将其设置成只读。同时,进行 force merge 操作。如果问题依然存在,则需要考虑扩容。此外,对索引进行 force merge ,还可以减少对global ordinals 数据结构的构建,减少对 fielddata cache 的开销

案例二

问题:Field data cache 过大,导致 full GC
现象: 集群整体响应缓慢,也没有特别多的数据读写。但是发现节点在持续进行 Full GC
分析: 查看 Elasticsearch 的内存使用,发现 fielddata.memorysize 占用很大空间。同时,数据不存在写入和更新,也执行过 segments merge。
解决: 将indices.fielddata.cache.size 设小,重启节点,堆内存恢复正常
建议: Field data cache 的构建比较重,Elasticsearch 不会主动释放,所以这个值应该设置的保守一些。如果业务上确实有所需要,可以通过增加节点,扩容解决

案例三

问题:复杂的嵌套聚合,导致集群 full GC
现象: 节点响应缓慢,持续进行 Full GC
分析: 导出 Dump 分析。发现内存中有大量 bucket 对象,经过查看日志发现存在复杂的嵌套聚合

解决: 优化聚合
建议: 在大量数据集上进行嵌套聚合查询,需要很大的堆内存来完成。如果业务场景确实需要,则需要增加硬件进行扩展。同时,为了避免这类查询影响整个集群,需要设置 Circuit Break和 search.maxbuckets 的数值

案例四

包含多种断路器,避免不合理操作引发的 OOM,每个断路器可以指定内存使用的限制
Parent circuit breaker: 设置所有的熔断器可以使用的内存的总量
Fielddata circuit breaker: 加载 fielddata 所需要的内存
Request circuit breaker: 防止每个请求级数据结构超过一定的内存(例如聚合计算的内存)
In flight circuit breaker: Request中的断路器
Accounting request circuit breaker: 请求结束后不能释放的对象所占用的内存

Circuit Breaker 统计信息:
GETnodes/stats/breaker?
Tripped 大于 0,说明有过熔断。Limit size 与estimated size 约接近,越可能引发熔断。千万不要触发了熔断,就盲目调大参数,有可能会导致集群出问题,也不因该盲目调小,需要进行评估。建议将集群升级到 7.x,更好的Circuit Breaker实现机制。增加了indices.breaker.total.use real memory 配置项,可以更加精准的分析内存状况,避免 OOM

四、内参分配最佳实践

1、jvm heap分配

es默认会给jvm heap分配2个G的大小,对于几乎所有的生产环境来说,这个内存都太小了。如果用这个默认的heap size,那么生产环境的集群肯定表现不会太好。
有两个方式来调节es中的jvm heap size。设置环境变量ES_HEAP_SIZE。当es进程启动的时候,会读取这个环境变量的值,然后设置为jvm的heap size。举例,可以这样来设置:export ES_HEAP_SIZE=10g。此外,还可以在启动es进程的时候,传递一个jvm的option,比如:ES_JAVA_OPTS=“-Xms10g -Xmx10g” ./bin/elasticsearch,但是要注意-Xms和-Xmx最小和最大堆内存一定设置的一样,避免运行过程中的jvm heap resize,非常耗时。

在老版本的es中,比如es 2.x里面,一般推荐用ES_HEAP_SIZE环境变量的方式来设置jvm heap size。
在新版本的es中,比如es 5.x里面,一般推荐在jvm.options文件里面去设置jvm相关的参数。

2、将机器上少于一半的内存分配给es

一个常见的问题就是将es进程的jvm heap size设置的过于大了。比如有一台64G的机器,要给es jvm size设置64G内存,不不合理。有人认为,直接将机器上的可用的内存都分配给es jvm heap,性能是绝对高的,因为大量的数据都可以缓存在内存里面。
虽然heap对于es来说是非常重要的,jvm heap被es用来存放很多内存中的数据结构来提供更快的操作性能。但是还有另外一个内存的用户,那就是lucene。lucene的设计就是要使用底层的os filesystem cache来缓存数据结构。lucene的segment是保存在单独的文件中的。因为这些segment是不可变的,所以这些文件实际上也从来不会改变。这样的话,就可以更好的缓存这些文件,底层的os cache会将hot segment驻留在内存中以供更快的访问。这些segment包括了倒排索引(为了全文检索)以及正排索引(为了聚合操作)。lucene的性能是严重依赖于底层的os的,但是如果给了过多的内存到es的jvm heap,那么就没有足够的内存留给lucene。这会极大的影响性能。

es的性能很大的一块,其实是由有多少内存留给操作系统的os cache,供lucene去缓存索引文件,来决定的。所以说lucene的os cache有多少是非常重要的。

一般建议的是,将50%的内存分配给es jvm heap,然后留50%的内存给os cache。留给os cache的内存是不会不使用的,lucene会将剩下的内存全部用光,用来cache segment file。如果我们没有对任何分词的text field进行聚合操作,那么我们就不需要使用fielddata,甚至可以考虑给os cache更多的内存,因为fielddata是要用jvm heap。如果给jvm heap更少的内存,那么实际上es的性能反而会更好,因为更多的内存留给了lucene用os cache提升索引读写性能,同时es的jvm heap的gc耗时会更少。

3、不要给jvm分配超过32G内存

还有另外一个原因不要将过多的内存分配给es的jvm heap。如果heap小于32G的化,jvm会用一种技术来压缩对象的指针,object pointer。在java中,所有的对象都会被分配到heap中,然后被一个pointer给引用。object pointer会指向heap中的对象,引用的是二进制格式的地址。

对于32位的系统来说,jvm最大的heap size就是4G,解释一下,32位,0和1值,0和1在32位的组合是2^32次方的字节,除以1024就是多少k,再除以1024就是多少mb,再除以1024就是多少gb,最后算下来就是4G。对于64位的系统来说,heap size可以更大,但是64位的object pointer会耗费更多的空间,因为object pointer更大了。比浪费更多内存空间更恶劣的是,过大的object pointer会在cpu,main memory和LLC、L1等多级缓存间移动数据的时候,吃掉更多的带宽。

所以jvm用了一种技术,叫做compressed oops来解决object pointer耗费过大空间的问题。这个技术的核心思想是,不要让object pointer引用内存中的二进制地址,而是让object pointer引用object offset。这就意味着32位的pointer可以引用400万个对象,而不是400万字节。这也意味着,使用32位的pointer,最大的heap大小可以到32G。此时只要heap size在32G以内,jvm就会自动启用32位的object pointer,因为32位的对象指针,足够引用32G的内存了,就可以用32位的pointer替代64位的pointer。但是32位的pointer比64位的pointer可以耗费更少的内存耗费。

如果给jvm heap分配的内存小于32G,此时jvm会自动使用32位的object pointer,同时是让pointer指向对象的offset,32位的object pointer就足以引用32G的内存,同时32位的pointer占用的内存空间很少,对cpu和memory之间移动数据的带宽开销也很少。这个过程就叫做compressed oops。

但是一旦越过了32G这个界限,就是给jvm heap分配了超过32G的内存,就没有办法用32位的pointer+引用object offset的模式了,因为32位的pointer最多引用32G的内存,超过了32G,就没法用32位pointer。不用32位pointer,就只能用64位pointer,才能引用超过32G的内存空间。此时pointer就会退回到传统的object pointer引用对象的二进制地址的模式,此时object pinter的大小会急剧增长,更多的cpu到内存的带宽会被占据,更多的内存被耗费。实际上,不用compressed oops时,如果给jvm heap分配了一个40~50G的内存的可用空间,实际上被object pointer可能都要占据十几G的内存空间,可用的空间量,可能跟使用了compressed oops时的32GB内存的可用空间,20多个G,几乎是一样的。

因此即使有很多内存,但是还是要分配给heap在32GB以内,否则的话浪费更多的内存,降低cpu性能,而且会让jvm回收更大的heap。

综上所述,如果给jvm heap分配超过32G的内存,实际上是没有什么意义的,因为用64位的pointer,1/3的内存都给object pointer给占据了,这段内存空间就浪费掉了。还不如分配32G以内,启用compressed oops,可用空间跟你分配50个G的内存,是一样的。

所以也正是因为32G的限制,一般来说,如果es要处理的数据量上亿的话,几亿,或者十亿以内的规模,建议是用64G的内存的机器比较合适,有个5台可以。给jvm heap分配32G,留下32G给os cache。

4、在32G以内的话具体应该设置heap为多大?

这个是根据具体情况而定的,不是固定死的,根据不同的jvm和平台而变。一般而言,将jvm heap size设置为31G比较安全一些。主要是要确保说,你设置的这个jvm heap大小,可以让es启用compressed oops这种优化机制。此外,可以给jvm option加入-XX:+PrintFlagsFinal,然后可以打印出来UseCompressedOops是否为true。这就可以让我们找到最佳的内存设置。因为可以不断调节内存大小,然后观察是否启用compressed oops。

举例来说,如果在mac os上启动一个java 1.7,同时将heap size设置为32600mb,那么compressed oops是会开启的;但是如果设置为32766m,compressed oops就不会开启。相反的是,使用jdk 1.8的化,分配32766m,compressed oops是会开启的,设置为32767m,就不会开启。所以说这个东西不是固定的。根据不同的操作系统以及jvm版本而定。

在es启动日志中,我们可以查看compressed oops是否开启,比如下面的字样:[2015-12-16 13:53:33,417][INFO ][env] [Illyana Rasputin] heap size [989.8mb], compressed ordinary object pointers [true]。

5、对于有1TB内存的超大内存机器该如何分配?

如果机器是一台超级服务器,内存资源甚至达到了1TB,或者512G,128G,该怎么办?首先es官方是建议避免用这种超级服务器来部署es集群的,但是如果我们只有这种机器可以用的话,我们要考虑以下几点:

(1)我们是否在做大量的全文检索?考虑一下分配4~32G的内存给es进程,同时给lucene留下其余所有的内存用来做os filesystem cache。所有的剩余的内存都会用来cache segment file,而且可以提供非常高性能的搜索,几乎所有的数据都是可以在内存中缓存的,es集群的性能会非常高

(2)是否在做大量的排序或者聚合操作?聚合操作是不是针对数字、日期或者未分词的string?如果是的化,那么还是给es 4~32G的内存即可,其他的留给es filesystem cache,可以将聚合好用的正排索引,doc values放在os cache中

(3)如果在针对分词的string做大量的排序或聚合操作?如果是的化,那么就需要使用fielddata,这就得给jvm heap分配更大的内存空间。此时不建议运行一个节点在机器上,而是运行多个节点在一台机器上,那么如果我们的服务器有128G的内存,可以运行两个es节点,然后每个节点分配32G的内存,剩下64G留给os cache。如果在一台机器上运行多个es node,建议设置:cluster.routing.allocation.same_shard.host: true。这会避免在同一台物理机上分配一个primary shard和它的replica shard。

6、swapping

如果频繁的将es进程的内存swap到磁盘上,会对服务性能造成很大影响,内存中的操作都是要求快速完成的,如果需要将内存页的数据从磁盘swap回main memory的化,性能会有多差。如果内存被swap到了磁盘,那么100微秒的操作会瞬间变成10毫秒,那么如果是大量的这种内存操作呢?这会导致性能急剧下降。因此通常建议彻底关闭机器上的swap,swapoff -a,如果要永久性关闭,需要在/etc/fstab中配置

如果没法完全关闭swap,那么可以尝试调低swappiness至,这个值是控制os会如何将内存swap到磁盘的。这会在正常情况下阻止swap,但是在紧急情况下,还是会swap。一般用sysctl来设置,vm.swappiness = 1。如果swappiness也不能设置,那么就需要启用mlockall,这就可以让我们的jvm lock住自己的内存不被swap到磁盘上去,在elasticsearch.yml中可以设置:bootstrap.mlockall: true。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2373648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

独立按键控制LED

目录 1.独立按键介绍 2.原理图 3.C51数据运输 解释&#xff1a;<< >> ​编辑 解释&#xff1a;& | 解释&#xff1a;^ ~ ​编辑 4.C51基本语句 5.按键的跳动 6.独立按键控制LED亮灭代码 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1…

计算机科技笔记: 容错计算机设计03 系统可信性的度量 偶发故障期 浴盆曲线 韦布尔分布

可靠性 简化表达式 偶发故障期&#xff0c;系统发生故障概率趋近于一个常数 浴盆曲线 MTTF和计算 韦布尔分布 马尔可夫链 可靠度

爬虫准备前工作

1.Pycham的下载 网址&#xff1a;PyCharm: The only Python IDE you need 2.Python的下载 网址&#xff1a;python.org&#xff08;python3.9版本之后都可以&#xff09; 3.node.js的下载 网址&#xff1a;Node.js — 在任何地方运行 JavaScript&#xff08;版本使用18就可…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】7.1 主流可视化工具对比(Tableau/Matplotlib/Python库)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 第七章 可视化工具集成&#xff1a;Tableau、Matplotlib与Python库深度对比7.1 主流可视化工具对比&#xff1a;技术选型的决策框架7.1.1 工具定位与核心能力矩阵7.1.2 数据…

操作系统实验习题解析 上篇

孤村落日残霞&#xff0c;轻烟老树寒鸦&#xff0c;一点飞鸿影下。 青山绿水&#xff0c;白草红叶黄花。 ————《天净沙秋》 白朴 【元】 目录 实验一&#xff1a; 代码&#xff1a; 解析&#xff1a; 运行结果&#xff1a; 实验二&#xff1a; 代码解析 1. 类设计 …

基于Arduino Nano的DIY示波器

基于Arduino Nano的DIY示波器&#xff1a;打造属于你的口袋实验室 前言 在电子爱好者的世界里&#xff0c;示波器是不可或缺的工具之一。它能够帮助我们观察和分析各种电子信号的波形&#xff0c;从而更好地理解和调试电路。然而&#xff0c;市面上的示波器价格往往较高&…

渠道销售简历模板范文

模板信息 简历范文名称&#xff1a;渠道销售简历模板范文&#xff0c;所属行业&#xff1a;其他 | 职位&#xff0c;模板编号&#xff1a;KRZ3J3 专业的个人简历模板&#xff0c;逻辑清晰&#xff0c;排版简洁美观&#xff0c;让你的个人简历显得更专业&#xff0c;找到好工作…

JAVA练习题(1) 卖飞机票

import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scnew Scanner(System.in);System.out.println("请输入飞机的票价&#xff1a;");int pricesc.nextInt();System.out.println("请输入月份&#xff1a;");…

杆件的拉伸与压缩变形

杆件的拉伸与压缩 第一题 Q u e s t i o n \mathcal{Question} Question 图示拉杆沿斜截面 m − m m-m m−m由两部分胶合而成。设在胶合面上许用拉应力 [ σ ] 100 MPa [\sigma]100\text{MPa} [σ]100MPa&#xff0c;许用切应力 [ τ ] 50 MPa [\tau]50\text{MPa} [τ]50MP…

企业开发平台大变革:AI 代理 + 平台工程重构数字化转型路径

在企业数字化转型的浪潮中&#xff0c;开发平台正经历着前所未有的技术革命。从 AST&#xff08;抽象语法树&#xff09;到 AI 驱动的智能开发&#xff0c;从微服务架构到信创适配&#xff0c;这场变革不仅重塑了软件开发的底层逻辑&#xff0c;更催生了全新的生产力范式。本文…

《汽车噪声控制》复习重点

题型 选择 填空 分析 计算 第一章 噪声定义 不需要的声音&#xff0c;妨碍正常工作、学习、生活&#xff0c;危害身体健康的声音&#xff0c;统称为噪声 噪声污染 与大气污染、水污染并称现代社会三大公害 声波基本概念 定义 媒质质点的机械振动由近及远传播&am…

Linux——MySQL约束与查询

表的约束 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合 法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有一个字段是email&#xff0c;要求是唯一的。 表的约束是为了防止插入不合法的…

Asp.Net Core IIS发布后PUT、DELETE请求错误405

一、方案1 1、IIS管理器&#xff0c;处理程序映射。 2、找到aspNetCore&#xff0c;双击。点击请求限制...按钮&#xff0c;并在谓词选项卡上&#xff0c;添加两者DELETE和PUT. 二、方案2 打开web.config文件&#xff0c;添加<remove name"WebDAVModule" />&…

STL-to-ASCII-Generator 实用教程

参阅&#xff1a;STL-to-ASCII-Generator 使用教程 开源项目网址 下载 STL-to-ASCII-Generator-main.zip 解压到 D:\js\ index.html 如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta id"ascii&q…

巡检机器人数据处理技术的创新与实践

摘要 随着科技的飞速发展&#xff0c;巡检机器人在各行业中逐渐取代人工巡检&#xff0c;展现出高效、精准、安全等显著优势。当前&#xff0c;巡检机器人已从单纯的数据采集阶段迈向对采集数据进行深度分析的新阶段。本文探讨了巡检机器人替代人工巡检的现状及优势&#xff0c…

国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件,并用前端对话框实现填空填表

不管是政府机关、公司企业&#xff0c;还是金融行业、教育行业等单位&#xff0c;在办公过程中都经常需要填写各种文书和表格&#xff0c;比如通知、报告、登记表、计划表、申请表等。这些文书和表格往往是用Word文件制作的模板&#xff0c;比方说一个通知模板中经常会有“关于…

RabbitMQ-高级特性1

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言消息确认机制介绍手动确认方法代码前言代码编写消息确认机制的演示自动确认automanual 持久化介绍交换机持久化队列持久化消息持久化 持久化代码持久化代码演示…

青藏高原东北部祁连山地区250m分辨率多年冻土空间分带指数图(2023)

时间分辨率&#xff1a;10年 < x < 100年空间分辨率&#xff1a;100m - 1km共享方式&#xff1a;开放获取数据大小&#xff1a;24.38 MB数据时间范围&#xff1a;近50年来元数据更新时间&#xff1a;2023-10-08 数据集摘要 多年冻土目前正在经历大规模的退化&#xff0c…

论文分享➲ arXiv2025 | TTRL: Test-Time Reinforcement Learning

TTRL: Test-Time Reinforcement Learning TTRL&#xff1a;测试时强化学习 https://github.com/PRIME-RL/TTRL &#x1f4d6;导读&#xff1a;本篇博客有&#x1f9a5;精读版、&#x1f407;速读版及&#x1f914;思考三部分&#xff1b;精读版是全文的翻译&#xff0c;篇幅较…

【计算机网络-传输层】传输层协议-TCP核心机制与可靠性保障

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 上篇文章&#xff1a;传输层协议-UDP 下篇文章&#xff1a; 网络层 我们的讲解顺序是&…