回答思路:先解釋spark的內存模型,再分情況介紹不同情況下的解決方案。總體思想是根據內存模型找出不夠的那壹塊內存,要麽提升占比,要麽整體增加。
oom通常出現在execution內存中,因為storage這塊內存在放滿之後,會直接丟棄內存中舊的數據,對性能有點影響但不會導致oom。存儲內存和執行內存可以互相借用內存空間。
而spark的oom問題主要分為三種情況:
①map執行後的內存溢出
--場景:maptask所運行的executor內存溢出。
增加堆內內存,申請的堆外內存也會隨之增加
--executor -memory?
增加堆外內存
--conf spark.excutor.memoryoverhead 2048
默認申請的堆外內存是Executor內存的10%。
②shuffle後內存溢出
reduce task去map壹邊拉取數據,壹邊聚合。reduce端有壹塊聚合內存,executor memory *0.2
解決方案:增加reduce聚合內存的比例,設置spark.shuffle.memoryfraction
增加executor memory的大小
減少reduce task每次拉取的數據量,設置spark.reducer.maxSizeInFlight 24m
③driver內存溢出
--場景壹:用戶在Dirver端口生成大對象,比如創建了壹個大的集合數據結構
解決思路:Ⅰ將大對象轉換成Executor端加載,比如調用sc.textfile
Ⅱ評估大對象占用的內存,增加dirver-menory的值
--場景二:從Executor端收集數據(collect)回Dirver端
解決思路:Ⅰ本身不建議將大的數據從executor端,collect回來。建議將driver端對collect回來的數據所作的操作,轉換成executor端rdd操作
Ⅱ若無法避免,估算collect需要的內存,相應增加driver-memory的值
--場景三:spark自身框架的消耗
主要由spark UI數據消耗,取決於作業的累計task個數
解決思路:Ⅰ從hdfs load的parition是自動計算,但在過濾之後,已經大大減少了數據量,此時可以縮小partitions。
? Ⅱ通過參數spark.ui.retainedStages/spark.ui.retainedjobs控制(默認1000)
2、shuffle file not found可能是什麽原因導致的報錯?
產生該報錯的原因可能是後壹個stage的task從上壹個stage的task所在的executor拉取數據,但是上壹個stage正在執行GC,導致數據沒有拉渠道,出現該錯誤。可以通過調整拉取的次數和間隔時間來避免此類事件發生。
val conf =new SparkConf()
.set("spark.shuffle.io.maxRetries","6')
.set("spark.shuffle.io.retrywait","60s")
3、棧溢出?
yarn-client模式下,Dirver是運行在本地機器上的,spark使用的jvm的permGen是128m,可能在client上測試沒有問題
yarn-cluster模式下,Dirver是運行在集群的某個節點上,使用的是沒有經過配置的默認配置,PermGen永久代大小為82m。運行時報棧溢出。
--解決方案:在spark-submit腳本中對相關參數進行設置
--conf spark.dirver.extraJavaOptions="-xx:PerSize=128M -xx:MaxPermSize=256m"