美文网首页Java
GC问题分析:YoungGC频繁和长时

GC问题分析:YoungGC频繁和长时

作者: 梅肯羅斯 | 来源:发表于2020-02-15 01:28 被阅读0次

    总结下工作中遇到的GC问题。

    一、JVM参数设置不当

    机器4G,部分JVM参数设置

    -Xmx3296m -Xms3296m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxGCPauseMillis=200 -XX:+UseG1GC 
    -XX:-OmitStackTraceInFastThrow -XX:MinHeapFreeRatio=30 -XX:MaxHeapFreeRatio=50
    

    现象:young GC比较频繁,并且不稳定,每1、2个小时会出现YGC次数激增,偶尔伴随Full GC,此时CPU状态也上升到100%。


    1
    2

    查看日志:


    image.png

    分析原因:G1 GC动态调整新生代大小(默认5%-60%),从日志看出调整后的Eden区太小,导致很容易发生young gc。

    解决方案:
    调整JVM参数,将新生代下限从5%调整到35%:

    -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=35 -XX:G1MaxNewSizePercent=60
    

    补充:Google时,看到说因为G1需要Mixed GC,Mixed GC会扫描Eden,Survivor,和1/8(默认)Old。因为比Young GC多扫描Old区,所以为了尽力实现最大停顿时间,在Mixed GC前的Young GC急剧缩小了Eden Heap的大小,所以调大最大停顿时间也能缓解此问题。

    结果:YGC次数更平稳,FGC未出现


    3

    二、代码不合理

    现象:每3小时出现一次YGC时间超过超过300ms,此时CPU和网络状态正常,只有内存增加。

    当时排障的日志没截图保存下来,简单说一下主要耗时就是Object Copy占了大量时间,如图红色框部分


    image.png

    日志中各参数含义可以参考:

    https://www.jianshu.com/p/ac1ba3479c08

    分析:通过代码发现每3个小时会全量拉一批某表的信息做本地缓存。Object Copy占了大量时间,说明需要Copy的对象很多。因为是缓存对象,所以不能回收。

    解决方案:使用增量刷新的方式。伪代码:

    int total = getTotalCount();
    int pageSize = 500;
    int(int i = 0 , i < total, i += pageSize){
      List list = exec("select * from my_table limit ?,?", i ,pageSize)
      CACHE.putAll(list);
    }
    

    采用这种方法需要注意的点:
    1.可能导致刷新的数据不全,在刷新缓存时如果有新数据插入,则可能导致部分的缓存没有刷新。该问题的优化方式之一是:更新完缓存后看缓存的size是否等于表中数据的条数,如果不等于,说明刷新缓存过程中出现了变动,可以重新更新缓存(CAS思想)。
    2.这种改进方法降低了吞吐量,一般来说这种定时任务都是以吞吐量为优先,改进这个问题是因为该问题影响了我系统的其他实时性功能,所以需不需要改进还是根据自己系统的需求。

    相关文章

      网友评论

        本文标题:GC问题分析:YoungGC频繁和长时

        本文链接:https://www.haomeiwen.com/subject/ivwsfhtx.html