Hadoop小文件影響及解決


一、小文件產生的原因

   當文件的大小遠遠小於HDFS block塊的大小(hadoop2:128m)就可以當作是一個小文件;具體產生的原因包括一下:

    1)實時計算時,如果窗口開的小,在hdfs上會產生很多小文件

    2)離線計算,批處理時,在spark或者mr時,沒有設置好partition或者reduce的個數,會產生小文件

    3)Flume采集數據時,沒有配置好具體的滾動策略,會產生小文件

    4)數據源本身存在很多小文件

 

二、小文件的影響

  1)元數據影響:namenode將文件系統的元數據存放在內存中,因此存儲的文件數目受限於 namenode的內存大小。HDFS中每個文件、目錄、數據塊 占用150Bytes。如果存放的文件數目過多的話會占用很大的內存甚至撐爆內存;

     2)mr任務影響:在mapreduce中,對每個文件都會啟動一個map task,如果小文件太多,影響性能;

  3)在hdfs的讀流程里,如果小文件越多,尋址花費的時間越多

 

三、如何處理小文件

  • 在向hdfs寫入數據前合並,包括map端合並小文件和reduce端合並小文件
    #設置map輸入合並小文件的相關參數:
    
    //每個Map最大輸入大小(這個值決定了合並后文件的數量,調大可以減小Mapper數),默認128M
    set mapred.max.split.size=1024*1024*512;  
    
    //一個節點上split的至少的大小(小於這個值會進行合並,這個值決定了多個DataNode上的文件是否需要合並)
    set mapred.min.split.size.per.node=1024*1024*512;
    
    //一個交換機下split的至少的大小(這個值決定了多個交換機上的文件是否需要合並)  
    set mapred.min.split.size.per.rack=100000000;
    
    //設置hive輸入端進行小文件合並
    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
    
    # 減少reduce的數量
    -- 除非知道數據量的分布,一般不直接設置
    set mapred.reduce.tasks=10;
    
    -- 每個reduce處理的數據量,實際上可能每個reduce 處理的數據量會超過它,默認1G 增加該參數,可以減小reduce數量
    set hive.exec.reducers.bytes.per.reducer=1073741824 
    
    
    # 設置map輸出和reduce輸出進行合並的相關參數:
    //設置map端輸出進行合並,默認為true
    set hive.merge.mapfiles = true
    
    //設置reduce端輸出進行合並,默認為false
    set hive.merge.mapredfiles = true
    
    //設置合並文件的大小
    set hive.merge.size.per.task = 256*1000*1000
    
    //當輸出文件的平均大小小於該值時,啟動一個獨立的MapReduce任務進行文件merge。
    set hive.merge.smallfiles.avgsize=16000000
  • 對hdfs上的已存在的小文件進行合並

    1)Hadoop Archive小文件歸檔:

      hadoop archive -archiveName event.har -p /app/event -r 3  sub_path sub_path2 /app/har

      event.har :歸檔文件的名稱

      /app/event:需要歸檔文件的父目錄

      sub_path: 子目錄,可以是多個,中間用空格分隔

      /app/har:存儲的目錄

      

      在歸檔結束之后,需要手動刪除歸檔后的路徑:

      hdfs dfs -rmr /app/event/sub_path

    2)CombineFileInputFormat<K,V> 小文件合並

    3)手動合並,先將hdfs上的文件copy到本地,本地合並后在上傳到hdfs

#!/bin/bash
bizdate=$1
path=$2
for (( i = 0; i < 10; i++ )); do
    bizhour="0${i}"
    echo "${bizdate} ${bizhour}"
    hdfs  dfs  -test -e /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/
    if [ $? -ne 1 ];
       then
         echo "進行hdfs操作"
         hdfs  dfs  -cat /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-00* | hdfs  dfs  -copyFromLocal - /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-11
         hdfs  dfs  -rmr /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-00*
    fi
    hdfs  dfs  -test -e /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/
    if [ $? -ne 1 ];
      then
        echo "進行hdfs操作"
        hdfs  dfs  -cat /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-00* | hdfs  dfs  -copyFromLocal - /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-11
        hdfs  dfs  -rmr /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-00*
    fi
done
for (( i = 10; i < 24; i++ )); do
    bizhour=${i}
    echo "${bizdate} ${bizhour}"
    hdfs  dfs  -test -e /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/
    if [ $? -ne 1 ];
       then
         echo "進行hdfs操作"
         hdfs  dfs  -cat /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-00* | hdfs  dfs  -copyFromLocal - /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-11
         hdfs  dfs  -rmr /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=access/part-00*
    fi
    hdfs  dfs  -test -e /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/
    if [ $? -ne 1 ];
      then
        echo "進行hdfs操作"
        hdfs  dfs  -cat /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-00* | hdfs  dfs  -copyFromLocal - /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-11
        hdfs  dfs  -rmr /${path}/bizdate=${bizdate}/bizhour=${bizhour}/log_type=action/part-00*
    fi
done

 

      

    

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM