1. 程式人生 > >記一次hive的記憶體溢位(OutOfMemoryError: Java heap space)排查

記一次hive的記憶體溢位(OutOfMemoryError: Java heap space)排查

轉載請註明出處:http://blog.csdn.net/gklifg/article/details/50418109

剛剛從java組轉崗找資料組,學習大資料的知識,開發語言也從java轉到python新奇之外也遇到了諸多問題,其中最令我頭疼的就是在hive上的統計任務總是三天兩頭地報告OutOfMemory一開始因為有別的同事的任務干擾,我以為是計算資源不夠導致的,但後來把任務轉移到了另一個集群后,問題仍然存在,讓我百思不得其解。


問題的具體描述如下:

統計邏輯使用python pyhs2連線hive,執行HQL查詢。單獨執行時都很順利,定時執行時,基本上4天中必有一天會掛掉,報OutOfMemory: Java heap space,這時候一般會重啟hiveServer2,於是各個問題就又不見了,直到下一個4天。

現在看起來一切都很清晰,但是當身處問題之中的時候,很多噪音是會擾亂視線,比如說不定期的其他任務(spark、mapreduce)插入,因為其他問題引起的其他同事手動重啟hiveServer2,這些都會擾亂整個問題的外在表現形式。以至於很難看出記憶體溢位是有一個明顯的週期的。

由於是OutOfMemory,想來想去也沒什麼好的辦法,只能監控一下jvm,看看那時候到底發生了什麼。不知什麼問題在AWS上沒法使用jmap -heap,無奈就先使用jstat

監控語句如下:

jstat -gcutil [程序號] 5000 --每5秒列印一次jvm各個記憶體區的狀態

另外找了一個監控系統記憶體的語句:

vmstat | sed -n '/[0-9]/p'

設定兩個語句將結果輸出到檔案裡後就開始等待問題出現,因為本人也是現學現賣,對於jvm的瞭解非常淺,當時發現jvm的永久代空間很開變成近100%,但不知道是不是有問題。

過了一個週末,HIVE果然還是掛了,查日誌的時候發現當時的jvm記憶體是這樣的:

S0      S1      E          O           P         YGC      YGCT      FGC         FGCT        GCT

0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13348   5176.146   5215.240
0.00   0.00 100.00 100.00  99.37  14086   39.094   13349   5176.532   5215.626
0.00   0.00 100.00 100.00  99.37  14086   39.094   13349   5176.532   5215.626
0.00   0.00 100.00 100.00  99.37  14086   39.094   13349   5176.532   5215.626
0.00   0.00 100.00 100.00  99.37  14086   39.094   13349   5176.532   5215.626

可以看到新生代和老年代都已經爆滿,永久代幾乎爆滿,jvm一直在做full GC,但是沒有效果,各個記憶體區都被佔用了。這種情況發生後同事直接重啟了hiveServer2,我沒有來的及檢視一下當時堆中的物件資訊,不知道有沒有什麼有價值的資訊在裡面。就現在的日誌來看,我發現老年代和持久代的記憶體只要上去了,就再沒有下降過,而當這兩塊區域飽和後,新生代也出現了這種現象。這時候忽然意識到,是有什麼資源沒釋放吧!?

一看程式碼,果然,有兩個指令碼pyhs2的連線沒有關閉!

java裡面連線都是框架管理的,平時沒管過,換到python來,忽視了這個重要的步驟,血的教訓啊,連線一定要關閉!另外總的來說這次問題的原因雖然相當低階,但是排查用到的手段和思維方式給了我很多收穫,自責的同時也有戰勝困難的喜悅,記錄下來,自勉。