JVM系统优化实践(11):GC如何搞垮线上系统

您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~


看了那么多G1 GC的传说,再来看看怎么预防GC把工程师精心设计的系统给搞垮。

在JVM的运行过程中,既有创建对象,又有GC(可能还有Stop the World),或者二者循环进行。而年轻代GC对系统的影响一般情况下不大,但有些特殊的情况,影响会非常大:

1、堆内存过小(只有几百M);

2、堆内存过大(有几十G),此时的垃圾回收器不能用ParNew,只能用G1。

那么老年代GC对系统的影响呢?取决于年轻代对象进入老年代的条件以及一些其他条件:

1、对象年龄判断:默认在年轻代存活15次之后,进入老年代;

2、动态年龄判断:若Minor GC后,Survivor中全部对象的大小之和>Survivor大小的50%,就把年龄最大的对象直接放进老年代;

3、Survivor空间不足:Minor GC后,存活对象太多,Survivor空间不足,则存活对象直接进入老年代。

如果年轻代的Survivor空间过小,上述的第二条和第三条就会频繁发生,而且老年代GC至少比年轻代GC慢10倍以上。

再来澄清一些概念,免得混淆:

1、Minor GC === Young GC;

2、Full GC = Young GC + Old GC + 元空间GC;

3、Major GC,这个概念最好不要用;

4、Mixed GC,是G1中特有的概念,指G1的混合回收阶段。

各类GC的触发时机:

1、Young GC的触发时机,年轻代的Eden区满了之后就会触发,采用复制算法完成GC;

2、Old GC的触发时机,年轻代历次Young GC后进入老年代的对象总和的平均大小 > 老年代可用空间;或者老年代空间不足;或者老年代空间使用率> 92%;

3、当存放类信息和各类常量的元空间区也满了的时候,就会触发Full GC。

案例一背景:

1、基于商家产生的大量数据,开发的一套Business Intelligence;

2、例如每天访客数量、成交量、付费转化率等等;

3、经营数据 -> Hadoop/Spark/Flink -> MySQL/ElasticSearch;

4、刚开始业务量不大,Eden=1G,S0=S1=100M。

它的技术痛点是:

1、前端实时自动刷新报表;

2、大数据量报表;

3、高并发特征:单机500次请求/秒,每次请求需要加载100K数据传给前端,因此有50M/秒的空间消耗;1G空间20秒填满;

4、Young GC频繁触发,每次耗时几十毫秒,暂时影响不大。

为了应对这种情形,配置升级:

1、加大机器内存:Eden=16G,S0=S1=1G;

2、按照50M/秒的消耗速度,需要320秒就能填满16G空间;

3、ParNew + CMS垃圾回收有严重卡顿现象,JDK升级到1.8以上,采用G1垃圾回收。

案例二背景:

1、某系统会不停地从MySQL及其他数据源里提取大量的数据加载到JVM里进行计算处理;

2、单台机器大概100次/分钟的数据提取和计算任务;

3、每次提取10000条数据,每次计算耗费10秒左右;

4、10000条大概消耗10M空间,100次/分 × 10M/次 = 1G/分;

5、Eden=1.2G,S0=S1=100M;

6、年轻代1分钟就会耗尽。

它多久触发一次Full GC呢?

1、每次计算10000条要10秒钟,假设剩余20次计算任务仍在计算;

2、10M/次 × 20次 = 200M空间无法回收;

3、200M > Survivor,执行空间担保流程后,对象直接进入老年代;

4、1.5G / 200M/分 = 7分,老年代7分钟就会被填满;

5、每7分钟触发一次Full GC,清空老年代。

GC优化方案:

1、在当前频率下,增加年轻代空间,增大Survivor;

2、如果将该系统的工作负荷扩大10倍;

3、100M/分钟空间消耗,Full GC的时间也会大大缩短;

4、只需十多秒就能触发一次Full GC;

5、使用大内存机器优化,JVM空间均扩大10倍;

6、使用G1垃圾回收。


感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

你可能感兴趣的:(jvm,java,GC,年轻代,老年代)