年轻代频繁GC,大量FlushEntityEvent等hibernate对象(hibernate的内存泄漏)问题解决

现象

  • 高并发请求,需要操作数据库。大量的查询、删除、插入、更新操作。
  • 一次请求需要处理10万条数据左右,每条数据处理,都需要查询、删除、插入、更新多次,操作多张表。
  • 为了防止内存溢出,一次处理1000条。在Controller层方法分页,处理在service层执行,这样每处理1000条,提交一次。
  • 程序初始运行很快,处理1000个大概10秒,后来逐步的越来越慢,逐步变大,变成几十、几百、直至一千多秒
  • 年轻代GC频繁,但是没有STW,GC时间也不长,影响不大
  • 重启项目后,重新执行,还是这种情况。一开始很快,后来越来越慢

排查

  • arthas
  • jmap
    在这里插入图片描述

结果

  • 最终定位到hibernate内存泄漏
  • FlushEntityEvent向上追踪调用堆栈,是hibernate查询方法q.list()
  • session没有清空,越来越多,释放不了
  • 正常使用没问题,但是高并发的时候,来不及释放清空session,越用越慢
  • 清空后可以,每1000条,7秒左右,直到处理完20万左右数据,仍然是10秒左右的时间,符合业务需求
  • 清空session对其他操作数据库的方法执行有影响,只修改了本方法,处理一批次1000条后,清空一次。为了排除对其他业务的影响,为了这个数据处理方法,单独部署一个服务。
  • 在dao层添加方法,获取当前session,并清空,先flushclear
    public void clearSession() {
        Session session = this.getCurrentSession();
        session.flush();
        session.clear();
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章