年輕代頻繁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();
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章