一次内存快溢出问题复盘

背景

服务的其中一个实例健康检查一直频繁上下线告警,已使用的堆内存几乎达到分配的最大值,运维导出堆栈、内存快照重启服务,接下来就是复盘。

原因

功能场景是分层推送信息。循环调用户中心服务接口分批查询指定用户群的用户,然后给这些用户推送消息。其中查询回来的用户id会在内存中用HashSet做去重操作,当时有两个任务同时在进行,两个HashSet装了两千多万个用户id,内存占用超过了1.9G,一直频繁GC,影响了业务线程。当时的jvm监控如下:
堆内存
图1
老年代
图2
GC情况
图3

图表分析

  • 图 1可以看到堆内存从上午8点开始一直锯齿型增长,因为那两个任务还没完成,HashSet内存一直释放不了,
  • 从图2看到,一直到上午11点老年代已经满了,之后对象晋升老年代失败就会full gc了
  • 从图3左上角看到,年轻代占用越来越多且无法回收
  • 从图3右下角看到,11点后每次GC的耗时达到了1min,这时候基本无法正常提供服务了

处理方案

1、临时注释去重操作的代码发版,后续再优化(布隆过滤器优化内存占用过大问题
2、反馈相关业务方使用不当问题。这次是业务方使用不当造成的,正常目标用户体量不到两百万,但是全量一千多万地发送了,还同时发两个。

总结与思考

1、程序用内存做缓存时,还是不能太乐观,要考虑极端情况导致内存溢出(一开始特意配了2G最大堆内存, T_T 没想到还碰上OOM)。
2、目前只有服务器总体内存使用告警,jvm内存异常却没告警,需要加上,以便及早发现问题
3、系统如果增加预览结果展示并提醒再次确认,或增加审批机制等提醒用户反复检查,是否可以避免这次的问题呢

补充说明

线上服务jvm参数

-Xms1024m
-Xmx2048m
-XX:-OmitStackTraceInFastThrow  大量抛出同样的异常的后,后面的异常输出将不打印堆栈
-XX:+UseParNewGC 新生代进行并行回收
-XX:AutoBoxCacheMax=20000 缓存自动装箱最大值
-XX:-UseBiasedLocking 禁用偏向锁
-XX:+CMSParallelRemarkEnabled  启用并行重标记,降低标记停顿
-XX:+UseConcMarkSweepGC 并发标记清除(CMS)收集器
-XX:CMSInitiatingOccupancyFraction=50 CMS对内存超过50%时开始GC
-XX:+CMSScavengeBeforeRemark  在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销,一般CMS的GC耗时 80%都在remark阶段
-XX:MaxTenuringThreshold=15 设置的是年龄阈值
-XX:+UseCMSInitiatingOccupancyOnly  只用设定的回收阈值(上面指定的50%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整.
-XX:CMSFullGCsBeforeCompaction=1  1Full GC后对内存空间进行压缩整理
-XX:+UseCMSCompactAtFullCollection Full GC后对内存空间进行压缩整理
-XX:+DisableExplicitGC 手动调用System.gc()不生效

CMS垃圾收集器处理过程有七个步骤:

1. 初始标记(CMS-initial-mark) ,会导致STW;
2. 并发标记(CMS-concurrent-mark),与用户线程同时运行;
3. 预清理(CMS-concurrent-preclean),与用户线程同时运行;
4. 可被终止的预清理(CMS-concurrent-abortable-preclean) 与用户线程同时运行;
5. 重新标记(CMS-remark) ,会导致STW;
6. 并发清除(CMS-concurrent-sweep),与用户线程同时运行;
7. 并发重置状态等待下次CMS的触发(CMS-concurrent-reset),与用户线程同时运行;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值