1. 程式人生 > >Spark將大量分割槽寫入HDFS報錯

Spark將大量分割槽寫入HDFS報錯

對大量的資料進行一系列的資料處理後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引數配置。

  1. 避免太高的併發度同時寫一個檔案。
    所以在呼叫write.parquet前,先使用repartition合併碎片分割槽。
    因為減少了分割槽數,下次再讀取這份資料進行處理時,減少了啟動task的開銷。

  2. 提高同時寫的上限。
    hdfs-site.xml中修改dfs.datanode.max.xcievers,將其設定為4096

     <property>
        <name>dfs.datanode.max.xcievers</name>
        <value>4096</value>
      </property>

    需要重啟dataNode生效。