jvm内存溢出

 最近运维人员反馈限时抢兑应用每天开始抢兑后,一会就发生内存溢出导致down机。准备分析dump日志信息,发现dump日志太大,java自带的工具和ibm的工具都不能打开,因为服务器是64位的机器,jvm最大的内容设置4G,日志大概也是4G左右,本地机器32位,基本都不能打开。

 切换思路,从业务功能和代码上进行梳理排查,功能主要是抢兑活动相关的代码量也不大,仔细对代码进行查看没有发现过大集合、没有忘记关闭的资源和连接,郁闷中...


再从整体梳理思路,发现抢兑活动的信息都是从memcached获取的,不过仔细分析业务逻辑发现在缓存中的存储方式有些异常,正常应该是每个抢兑活动存储一个key-value,多个抢兑活动应该有多个key-value才对,结果发现开发者省事就在memcached中存储一个key-value,value的内容是一组抢兑活动了列表,当时抢兑活动已经有几百个,不仅有抢兑活动的基本信息和描述信息(富文本内容比较大),还有关联的商品的一些信息;分析怀疑此数据比较大,需要占用虚拟机很大的连续内存空间,在抢兑的几分钟内,并发量非常大,导致没有jvm经过回收后无法分配如此大的连续内存,从而导致内存溢出。


下面要验证推理过程,jvm年老代是用CMS并发收集算法,此算法的缺点是会产生内存碎片,因为其原理是标记-清理,不对内存进行整理。不过由于内存碎片,导致不能给大对象分配是,jvm会通过FULL-GC对eden区域和年老代进行回收,应该也会腾出一些空间分配,这时就要结合业务场景,正好是业务抢兑,瞬时并发量很高,其它内存也都被占用,导致FULL-GC后依然没有足够的内存,而内存溢出。


我们对memcached的value大小进行验证,发现其占内存大小有3M多,哪为什么网络流量基本没有异常,客户端程序判断超过1M时,会进行压缩,压缩后存储在memcaced,接收后然后在虚拟机内解压,因为使用了CMS并发算法,eden区域设置的较小,导致很快就直接在年老带进行内存分配了。


对调用memcached的程序逻辑进行了优化,按照每个抢兑活动一条key-value,上线后经过一段时间的观察,没有在抢兑时出现内存溢出问题。


终于解决了,做个记录以便以后参考,使用共享缓存一定要注意不要放大对象,尤其是在高并发的情况下,很容易导致jvm无内存分配引起的内存溢出。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值