本文旨在解析 spark on Yarn 的內存管理,使得 spark 調優思路更加清晰
內存相關參數
spark 是基於內存的計算,spark 調優大部分是針對內存的,了解 spark 內存參數有也助於我們理解 spark 內存管理
- spark.driver.memory:默認 512M
- spark.executor.memory:默認 512M
- spark.yarn.am.memory:默認 512M
- spark.yarn.driver.memoryOverhead:driver memory * 0.10, with minimum of 384
- spark.yarn.executor.memoryOverhead:executor memory * 0.10, with minimum of 384
- spark.yarn.am.memoryOverhead:am memory * 0.10, with minimum of 384
- executor-cores:executor 相當於一個進程,cores 相當於該進程里的線程
內存解析
spark.xxx.memory / --xxx-memory 是 JVM 堆區域,但是 JVM 本身也會占用一定的堆空間,這部分由 spark.yarn.xxx.memoryOverhead 確定,二者關系如下圖
內存分配
為了更好的利用 spark 內存,通常我們需要在 Yarn 集群中設置如下參數 【非必須】
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>106496</value> <!-- 104G --> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>2048</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>106496</value> </property> <property> <name>yarn.app.mapreduce.am.resource.mb</name> <value>2048</value> </property>
- yarn.app.mapreduce.am.resource.mb:am 能申請的最大內存
- yarn.nodemanager.resource.memory-mb:nodemanager 能申請的最大內存
- yarn.scheduler.minimum-allocation-mb:任務調度時一個 container 可申請的最小內存
- yarn.scheduler.maximum-allocation-mb:任務調度時一個 container 可申請的最大內存
yarn.scheduler.minimum-allocation-mb 是 Container 的內存基本單位,也就是說 Container 的內存必須是 yarn.scheduler.minimum-allocation-mb 的整數倍,
比如 yarn.scheduler.minimum-allocation-mb 設置為 2G,2048M,
如果內存申請為 512M,512+384<2048M,會被分配 2G 內存,
如果內存申請為 3G,3072+384=3456M<4096M,會被分配 4G 內存,
如果申請內存為 6G,6144+614=6758<8192M,會被分配 8G 內存, 【max(6144*0.1, 384)=614】
所以當設定 --executor-memory 為 3G 時,Container 實際內存並非 3G
常見問題
常見的問題無非就是 內存不足 或者 container 被殺死
- Removing executor 5 with no recent heartbeats: 120504 ms exceeds timeout 120000 ms
- Container killed by YARN for exceeding memory limits
- Consider boosting spark.yarn.executor.memoryOverhead
- spark-OutOfMemory:GC overhead limit exceeded
常規思路
1. 第一解決辦法就是增加總內存 【此法不能解決所有問題】
2. 其次考慮數據傾斜問題,因為數據傾斜導致某個 task 內存不足,其它 task 內存足夠
// 最簡單的方法是 repartition 【此法不能解決所有問題】
3. 考慮增加每個 task 的可用內存
// 減少 Executor 數
// 減少 executor-cores 數
參數設置注意事項
executor-memory
1. 設置過大,會導致 GC 過程很長,64G 是推薦的 內存上限 【根據硬件不同,可尋找合適的上限】
2. 設置過小,會導致 GC 頻繁,影響效率
executor-cores
1. 設置過大,並行度會很高,容易導致 網絡帶寬占滿,特別是從 HDFS 讀取數據,或者是 collect 數據回傳 Driver
2. 設置過大,使得多個 core 之間爭奪 GC 時間以及資源,導致大部分時間花在 GC 上
參考資料:
https://www.cnblogs.com/saratearing/p/5813403.html#top
https://blog.csdn.net/pearl8899/article/details/80368018
https://www.so.com/s?q=with+minimum+of+384&src=se_zoned
https://blog.cloudera.com/how-to-tune-your-apache-spark-jobs-part-2/ 英文博客