爲什麼我們需要調GC
如果是在以前,ETL爲王的年代,我們其實大可不必去調試,使用默認的 Parallel GC就可以了。但是隨着發展,實時流計算以及AdHoc查詢,對JVM的要求:高吞吐低延遲,又變得非常重要。和傳統Web不同,通常如果一個JVM發生Full GC,僅僅會影響當前到訪問這個JVM的用戶的響應。而對於Spark這種,一個用戶的一個查詢有可能會發生在所有的JVM身上,這意味着有任何一個JVM發生了Full GC都會導致極大的延遲。就如同海量服務器幾乎時刻有可能發生硬盤損壞,而足夠多的Executor也會使得幾乎每次查詢都能遇到Full GC。Parallel GC長達幾十秒甚至分鐘級別的Full GC 會使得即席查詢化爲泡影。
所以對於流式計算以及AdHoc查詢,優化GC是必選項。
GC調優文章推薦
因爲現階段,相當部分的用戶應該還在使用Spark 2.x 以及JDK8. JDK8 可選擇不多,基本意味着你只有CMS以及G1可選。
CMS/G1都有較多的參數控制,這是優勢也是缺點,缺點是你需要不斷嘗試直到找到適合你的參數,並且你還需要了解每個參數背後的含義。
這裏推薦一篇文章:[爲你的spark程序調優JAVA垃圾回收](https://xinze.fun/2020/01/11/爲你的spark程序調優JAVA垃圾回收/) 該文翻譯自數磚15年的一篇[博文](https://databricks.com/blog/2015/05/28/tuning-java-garbage-collection-for-spark-applications.html). 儘管五年過去了,我個人認爲價值還是很大的。如果複製不方便,你也可以點擊原文。
還有一個更好的選擇
JDK 14中的ZGC 已經比較穩定了,ZGC也是近些年GC發展的最新成果,我個人認爲是劃時代的。ZGC有朋友實測效果非常好,55G的堆,可控制在10ms,通常3ms左右。缺點是Spark 3.0之前還不支持JDK 14,儘管你可以做一些修改使得當前的Spark(2.4.x)能夠運行在JDK 14上。另外如果你使用到了老的版本的Guava庫(<16)中的ClassPath,那麼也可能無法正確的運行在JDK 14上。