前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch中关于JVM和垃圾回收的介绍

Elasticsearch中关于JVM和垃圾回收的介绍

作者头像
用户7634691
发布2021-01-05 14:38:59
1.6K0
发布2021-01-05 14:38:59
举报

关于堆内存大小的设置

ES官方建议JVM中设置的最大堆内存大小,不超过节点RAM的一半,最大不超过32GB,并且XmsXmx相等。我们一个个说明。

首先为啥建议XmsXmx相等,这其实是个约定的配置了。并不仅限于ES,很多基于JAVA的服务在生产环境中都是建议这个配置。核心的原因在于减少JVM的时间开销,因为当Xms不够用时,JVM会继续想OS申请内存,这必然会带来额外的时间开销。如果你预测你的应用最终差不多用到Xmx,把这两个值设置成一样是个比较好的选择。

不超过系统RAM的一半,这个主要是出于文件系统缓存的考虑。我们知道Lucene的segment是一个个操作系统的文件,并且一但生成就不能更改,也就是只读的。所以操作系统也会把这些段文件缓存起来,以便更快的访问。这部分内存在查询量比较大的场景下,也会很快被lucene消耗掉。所以不用担心浪费的问题。反而如果操作系统的RAM过小,在ES查询并发比较大的时候,一个是查询比较慢,另外就是磁盘IO比较高。

关于不超过32GB的问题。这个问题要想搞明白,需要一些操作系统底层的知识储备。

原因是jvm在内存小于32G的时候会采用一个内存对象指针压缩技术。在java中,所有的对象都分配在堆上,然后有一个指针引用它。指向这些对象的指针大小通常是CPU的字长的大小,比如4字节或者8字节,取决于你是32位的系统,还是64位的系统。

很多时候,如果只用32bit位往往不够,因为它最大只能表示到4GB的地址,但是生产环境中服务器内存往往大于这个数。直接用64bit表示呢,又很浪费空间,因为64bit最大可以表示的寻址空间为2的64次方bit,转化单位是

代码语言:javascript
复制
2147483648GB。

另外一个知识点是,操作系统要求地址都必须是8的整数倍,这就是我们常听说的内存对齐。内次对齐这是主要是出于性能的考虑,CPU对于这样的地址访问更快。地址是8的倍数意味着低三位总是0。

JVM既然已经知道了这三位必然是0,就干脆把它利用起来,让这三个位也存储有意义的值。

在堆中是32位,和三个右移的0。在寄存器中用来寻址的依然是35位,2的35次方=32G。也就是说,使用32位,来达到35位oop所能引用的堆内存空间。

当JVM需要在内存中找到一个对象时,它将指针向左移动3位(内存对齐,寻址)。另一方面,当向堆加载指针时,JVM将指针向右移动3位以丢弃之前添加的零。

关于垃圾回收

ES默认的JVM配置使用的垃圾回收器是CMS,打开默认的配置文件,通常能看到如下的配置:

代码语言:javascript
复制
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

第一行表示垃圾回收使用CMS,第二行表示指设定CMS在对老年代占用率达到75%的时候开始GC,避免老年代占满触发fullGC。

UseCMSInitiatingOccupancyOnly一般和上面那个配合一起使用,设定的回收阈值(上面指定的75%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整。

通常在生产上,我们的服务器堆内存都配合的比较大(一般都会超过16G)。官方建议使用G1垃圾回收。因为这种大堆内存的场景,CMS一般等到老年代占用很大的时候进行回收,停顿时间太长,这对大部分应用程序是致命的。

而G1相对更加智能,对停顿时间可以预测,对于大堆回收垃圾的效率更高。下面是在一篇国外的博客上找到的二者在同一个ES集群环境中测试的对比图,上面是使用CMS的测试结果,下面是G1的测试结果,你可以感受下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 犀牛的技术笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于堆内存大小的设置
  • 关于垃圾回收
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档