Spark將大量分割槽寫入HDFS報錯
阿新 • • 發佈:2019-02-11
對大量的資料進行一系列的資料處理後DataFrame
此時有2W個分割槽(170W條資料,因此每個分割槽數量只有幾百條),此時使用parquet
命令,將會往一個hdfs檔案中同時寫入了大量的碎檔案。
提示(省略無用資訊):
WARN TaskSetManager: Lost task: org.apache.spark.SparkException: Task failed while writing rows. WARN TaskSetManager: Lost task:org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException): No lease on /user/xx/sample_2016/_temporary/0/_temporary/attempt_201604141035_0058_m_019029_0/part-r-19029-1b93e1fa-9284-4f2c-821a-c83795ad27c1.gz.parquet: File does not exist. Holder DFSClient_NONMAPREDUCE_1239207978_115 does not have any open files.
原因
提示為檔案操作超租期,由於多個task操作寫一個檔案,其中某個task完成任務後刪除了臨時檔案引起。
該引數和dfs.datanode.max.xcievers
有關,預設為256。
dfs.datanode.max.xcievers
表示每個datanode任一時刻可以開啟的檔案數量上限。
解決方法
有兩個解決方法,一種是修改spark程式碼,一種是修改hdfs引數配置。
避免太高的併發度同時寫一個檔案。
所以在呼叫write.parquet
前,先使用repartition
合併碎片分割槽。
因為減少了分割槽數,下次再讀取這份資料進行處理時,減少了啟動task的開銷。提高同時寫的上限。
在hdfs-site.xml
中修改dfs.datanode.max.xcievers
,將其設定為4096<property> <name>dfs.datanode.max.xcievers</name> <value>4096</value> </property>
需要重啟dataNode生效。