Spark專案實戰-troubleshooting之解決JVM GC導致的shuffle檔案拉取失敗
一、shuffle檔案拉取失敗的背景介紹
我們知道Executor是一個JVM程序,在其內部有一個BlockManager用於管理該executor的一些資料。 Map端的task在往磁盤裡寫檔案的時候,會通過BlockManager來維護底層的資料,同時也會將資料的元資訊寫入到Driver中。 下一個stage的task拉取資料的時候會從Driver獲取拉取資料的元資訊,找到executor並從BlockManager拉取屬於自己的檔案裡的資料。如下:
但是有時會出現的一種非常普遍的情況,在spark的作業中報shuffle file not found的異常。而且,它是偶爾才會出現的一種情況。有的時候,出現這種情況以後,會重新去提交stage、task。重新執行一遍發現就好了,沒有這種錯誤了。
為什麼會出現這種情況?我們知道executor是一個JVM程序,可能記憶體不是很夠用了。那麼此時可能就會執行GC(minor GC or full GC)。總之一旦發生了JVM之後,就會導致executor內所有的工作執行緒全部停止,比如BlockManager、基於netty的網路通訊。那麼此時下一個stage的executor可能還沒有停止掉,task想要去上一個stage的task所在的exeuctor,去拉取屬於自己的資料,結果由於對方正在gc,就導致拉取了半天沒有拉取到。就很可能會報出:shuffle file not found。但是可能下一個stage又重新提交了stage或task以後,再執行就沒有問題了,因為可能第二次就沒有碰到JVM在gc了。
二、如何解決shuffle file not found異常?
2.1、spark.shuffle.io.maxRetries配置
該配置的意思是說,shuffle檔案拉取的時候,如果沒有拉取到(拉取失敗),最多或重試幾次(會重新拉取幾次檔案),預設是3次。
2.2、spark.shuffle.io.retryWait配置
該配置的意思是說,每一次重試拉取檔案的時間間隔,預設是5s鍾。預設情況下,假如說第一個stage的executor正在進行漫長的full gc。第二個stage的executor嘗試去拉取檔案,結果沒有拉取到,預設情況下,會反覆重試拉取3次,每次間隔是五秒鐘。最多隻會等待3 * 5s = 15s。如果15s內,沒有拉取到shuffle file,就會報出shuffle file not found。
針對這種情況,我們完全可以進行預備性的引數調節。增大上述兩個引數的值,達到比較大的一個值,儘量保證第二個stage的task一定能夠拉取到上一個stage的輸出檔案,避免報shuffle file not found。然後可能會重新提交stage和task去執行。那樣反而對效能也不好。
spark.shuffle.io.maxRetries 60
spark.shuffle.io.retryWait 60s
最多可以忍受1個小時沒有拉取到shuffle file。只是去設定一個最大的可能的值,full gc不可能1個小時都沒結束吧。