Spark——系統調優
JVM層
- 降低cache操作的記憶體佔比
Spark中,堆記憶體又被劃分成了兩塊:
- 專門用來給RDD的cache、persist操作進行RDD資料快取用的;
- 用來給spark運算元函式的執行使用的,存放函式中自己建立的物件。
預設情況下,給RDD cache操作的記憶體佔比是0.6,即60%的記憶體都給了cache操作了。但是問題是,如果某些情況下cache佔用的記憶體並不需要佔用那麼大,
問題在於task運算元函式中建立的物件過多,然後記憶體又不太大,導致了頻繁的minor gc,甚至頻繁full gc,導致spark頻繁的停止工作。效能影響會很大。
針對上述這種情況,這個時候可以將其記憶體佔比適當降低。怎麼判斷在什麼時候調整RDD cache的記憶體佔用比呢?
其實通過Spark監控平臺就可以看到Spark作業的執行情況了,包括每個task的執行時間、gc時間等等。如果發現task頻繁的gc,就可以去調整cache的記憶體佔用比了。
在程式碼中新增如下配置來設定:
SparkConf.set("spark.storage.memoryFraction","0.6")
- 堆外記憶體的調整
-
- 問題提出
- 問題提出
有時候,如果你的spark作業處理的資料量特別特別大,幾億資料量;然後spark作業一執行就會出現類似shuffle file cannot find,executor、task lost,out of memory(記憶體溢位)等這樣的錯誤。
這是因為可能是說executor的堆外記憶體不太夠用,導致executor在執行的過程中,可能會記憶體溢位;然後可能導致後續的stage的task在執行的時候,可能要從一些executor中去拉取shuffle map output檔案,
但是executor可能已經掛掉了,關聯的blockmanager也沒有了;所以可能會報shuffle output file not found;resubmitting task;executor lost 這樣的錯誤;最終導致spark作業徹底崩潰。
上述情況下,就可以去考慮調節一下executor的堆外記憶體。也許就可以避免報錯;此外,有時,堆外記憶體調節的比較大的時候,對於效能來說,也會帶來一定的提升。
-
- 解決方案
在spark-submit腳本里面新增如下配置。預設情況下,這個堆外記憶體上限大概是300多M;我們通常專案中真正處理大資料的時候,這裡都會出現問題導致spark作業反覆崩潰無法執行;
此時就會去調節這個引數,到至少1G或者更大的記憶體。通常這個引數調節上去以後,就會避免掉某些OOM的異常問題,同時呢,會讓整體spark作業的效能,得到較大的提升。
--conf spark.yarn.executor.memoryOverhead=2048
注:看名字,顧名思義,以上設定針對的是基於yarn的提交模式
- 連線等待時長的調整
-
問題提出
-
executor會優先從自己本地關聯的BlockManager中獲取某份資料。如果本地block manager沒有的話,那麼會通過TransferService,去遠端連線其他節點上executor的block manager去獲取。
而此時上面executor去遠端連線的那個executor,因為task建立的物件特別大,特別多, 頻繁的讓JVM堆記憶體滿溢,正在進行垃圾回收。
而處於垃圾回收過程中,所有的工作執行緒全部停止,相當於只要一旦進行垃圾回收,spark / executor停止工作,無法提供響應。 此時呢,就會沒有響應,無法建立網路連線,會卡住。
spark預設的網路連線的超時時長是60s;如果卡住60s都無法建立連線的話,那麼就宣告失敗了。碰到一種情況,有時候報錯資訊會出現一串類似file id not found,file lost的錯誤。
這種情況下,很有可能是task需要處理的那份資料的executor在正在進行gc。所以拉取資料的時候,建立不了連線。然後超過預設60s以後,直接宣告失敗。
幾次都拉取不到資料的話,可能會導致spark作業的崩潰。也可能會導致DAGScheduler,反覆提交幾次stage。TaskScheduler,反覆提交幾次task。大大延長我們的spark作業的執行時間。
-
-
解決方案
-
在spark-submit指令碼中新增如上引數,調節這個值比較大以後,通常來說,可以避免部分的偶爾出現的某某檔案拉取失敗,某某檔案lost掉的錯誤。
--conf spark.core.connection.ack.wait.timeout=300
引用: