全网疯传!看完就能懂!ElasticSearch-垃圾回收器优化(1)

本文深入探讨了ElasticSearch集群的JVM垃圾回收问题,重点分析了ParNew+CMS垃圾回收器的工作机制。面对CPU高负载和服务超时,通过监控发现频繁的Young GC和偶尔的Old GC。文章详细解释了对象分配过程,讨论了G1收集器的优势,如内存碎片整理和可控的STW。同时,提到了Remembered Sets和Collection Set在G1中的角色,以及如何调整和优化这些参数以提升系统性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • es集群配置:16核cpu,内存64G,磁盘200G
  • JDK版本:1.8
  • 垃圾回收器: CMS+ParNew

部署在这个集群的服务偶尔会遇到服务超时的情况,从kibana监控中可以看到,服务超时情况发生时,es服务器cpu较高。es存在young gc频繁,old gc 低频率,每天约出现2-4次。

image

image

查看过去一小时的监控情况,发现young gc 比较频繁,大量对象最终进入了老年代,通过old gc被回收掉了。

image

查看GC日志,log里99%都是GC (Allocation Failure)造成的young gc。Allocation Failure表示向young generation(eden)给新对象申请空间,但是young generation(eden)剩余的合适空间不够所需的大小导致的minor gc。

image

Desired survivor size 56688640 bytes, new threshold 6 (max 6)
- age   1:    6717288 bytes,    6717288 total
- age   2:    6025032 bytes,   12742320 total
- age   3:     987872 bytes,   13730192 total
- age   4:        176 bytes,   13730368 total
- age   5:        336 bytes,   13730704 total
- age   6:      93864 bytes,   13824568 total
  • Desired survivor size表示survivor区域允许容纳的最大空间大小为56688640 bytes
  • max 6 表示对象经过6次gc后依然存活直接进入老年代
  • 对象列表为此次gc之后,survivor当前存活对象的年龄大小分布,下次gc如果对象没释放的话,超过阈值的(age=6 or 占用空间 > 56688640)对象将晋升到old generation。

JVM 垃圾回收

当代主流虚拟机(Hotspot VM)的垃圾回收都采用“分代回收”的算法。“分代回收”是基于这样一个事实:对象的生命周期不同,所以针对不同生命周期的对象可以采取不同的回收方式,以便提高回收效率。 image

  • 新生代:分三个区:一个Eden区,两个Survivor区,默认内存占比8:1:1。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到两个Survivor区(中的一个)。当这个Survivor区满时,此区的存活且不满足“晋升”条件的对象将被复制到另外一个Survivor区。对象每经历一次Minor GC,年龄加1,达到“晋升年龄阈值”后,被放到老年代。
  • 老年代:在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代。
  • java8已经没有持久代了,改为元数据区,主要存放元数据,例如Class、Method的元信息。

对象分配过程

  • 对象比较大的时候,超过-XX:PretenureSizeThreshold设置值时,直接分配到老年代;
  • 向eden申请空间创建新对象,eden没有合适的空间,因此触发minor gc
  • minor gc将eden区及from survivor区域的存活对象进行处理:
    • 如果这些对象年龄达到阈值(MaxTenuringThreshold),则直接晋升到年老代
    • 若要拷贝的对象太大,那么不会拷贝到to survivor,而是直接进入年老代
    • 若to survivor区域空间不够/或者复制过程中出现不够,则发生survivor溢出,直接进入年老代
    • 其他的,若to survivor区域空间够,则存活对象拷贝到to survivor区域
  • 此时eden区及from survivor区域的剩余对象为垃圾对象,直接抹掉回收,释放的空间成为新的可分配的空间
  • minor gc之后,若eden空间足够,则新对象在eden分配空间;若eden空间仍然不够,则新对象直接在年老代分配空间

垃圾回收器

  • 新生代收集器有:Serial(单线程),ParNew(多线程),Paraller Scavenge(侧重于吞吐量控制)
  • 老年代收集器有:CMS(获取最短回收停顿时间为目标的回收器,该回收器是基于“标记-清除”算法实现的), Serial old,Parallel Old
  • G1收集器可作用与新生代和老年代(JDK9默认垃圾收集器)

ParNew+CMS工作机制

-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75   //老年代内存使用率超过75%触发垃圾回收
-XX:+UseCMSInitiatingOccupancyOnly

ParNew:复制算法,将内存分为大小相等的两块,每次使用其中的一块一块用完时,将存活的对象复制到另一块。 CMS:使用标记-清除算法。整个过程分为四步:

  • 初始标记:STW,标记GC Roots能关联到的对象,速度很快
  • 并发标记:GC Roots Tracing过程。耗时。和用户线程一起执行(并行)
  • 重新标记:STW,标记并发标记过程中程序运行导致标记变化的对象,时间比初始标记长,远比并发标记短
  • 并发清除:耗时。和用户线程一起执行(并行)

G1

G1收集器的设计目标是取代CMS收集器,它同CMS相比,在以下方面表现的更出色:

  • G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
  • G1的Stop The World(STW)更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。并基于用户指定的停顿时间来选择进行垃圾回收的区块数量。G1 采用增量回收的方式,每次回收一些区块,而不是整堆回收。
  • G1 收集线程在标记阶段和应用程序线程并发执行,标记结束后,G1 也就知道哪些区块基本上是垃圾,存活对象极少,G1 会先从这些区块下手,因为从这些区块能很快释放得到很大的可用空间,这也是为什么 G1 被取名为 Garbage-First 的原因。

G1的各代存储地址是不连续的,每一代都使用了n个不连续的大小相同的Region,每个Region占有一块连续的虚拟内存地址。如下图所示:

image

Remembered Sets(Rset)

逻辑上说每个Region都有一个RSet,RSet记录了其他Region中的对象引用本Region中对象的关系。

Collection Set(CSet)

记录了GC要收集的Region集合,集合里的Region可以是任意年代的。

G1工作模式

  • YoungGC年轻代收集

在分配一般对象(非巨型对象)时,当所有eden region使用达到最大阀值并且无法申请足够内存时,会触发一次YoungGC。每次younggc会回收所有Eden以及Survivor区,并且将存活对象复制到Old区以及另一部分的Survivor区。

  • mixed gc

最后

由于篇幅限制,小编在此截出几张知识讲解的图解,有需要的程序猿(媛)可以点赞后戳这里免费领取全部资料获取哦

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

-8GIZV0hh-1628146035376)]

[外链图片转存中…(img-V5Pdpaf4-1628146035377)]

[外链图片转存中…(img-Ijc04DLI-1628146035378)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值