2011-08-22 80 views
12

我最近在Hadoop中設置了LZO壓縮。在HDFS中壓縮文件最簡單的方法是什麼?我想壓縮文件,然後刪除原件。我應該使用IdentityMapper和使用LZO壓縮的IdentityReducer創建MR作業嗎?Hadoop:在HDFS中壓縮文件?

回答

6

我建議你寫一個MapReduce作業,就像你說的那樣,它只是使用Identity映射器。當你處理它時,你應該考慮將數據寫入序列文件以提高性能加載。您還可以按塊級和記錄級壓縮存儲序列文件。呦應該看看什麼對你最有效,因爲兩者都針對不同類型的記錄進行了優化。

-3

那麼,如果你壓縮一個文件,你可能會節省一些空間,但你不能真正使用Hadoop的能力來處理該文件,因爲解壓縮必須由一個Map任務順序完成。如果你有很多文件,有Hadoop Archive,但我不確定它包含任何類型的壓縮。壓縮的主要用例我能想到的是壓縮要發送到Reduces的地圖的輸出(保存在網絡I/O上)。

哦,要回答你的問題更完整,你可能需要實現自己的RecordReader和/或InputFormat,以確保整個文件被單個Map任務讀取,並且它使用了正確的解壓過濾器。

+0

Hadoop集成了壓縮庫,請參閱http://www.cloudera.com/blog/2009/ 06 /並行LZO-可分離的壓縮換的hadoop /。 – schmmd

+0

有趣。我以爲你在談論輸入被壓縮,而不是壓縮輸出,對不起。你關心輸出文件中數據的排序嗎?如果您不關心輸出文件的排序,您可以輕鬆使用文件系統API並將FSDataOutputStream包裝在LZO壓縮過濾器中。如果你這樣做,那麼FileOutputFormat.setCompressOutput()和setOutputCompressorClass()。在Javadoc中是正確的,通過Google在10秒內發現它。 – Drizzt321

19

對我來說,編寫一個Hadoop Streaming作業來壓縮文件的開銷較低。

這是我運行命令:

hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-streaming-0.20.2-cdh3u2.jar \ 
    -Dmapred.output.compress=true \ 
    -Dmapred.compress.map.output=true \ 
    -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \ 
    -Dmapred.reduce.tasks=0 \ 
    -input <input-path> \ 
    -output $OUTPUT \ 
    -mapper "cut -f 2" 

我也通常會藏匿在一些情況下,一個臨時文件夾輸出出錯:

OUTPUT=/tmp/hdfs-gzip-`basename $1`-$RANDOM 

,還應注意,我不知道在流式作業中指定reducer,但您當然可以。它將強制所有行進行排序,這可能需要很長時間才能處理大文件。可能有一種方法可以通過重寫分區程序來解決這個問題,但我沒有想到這一點。這個不幸的部分是,你可能會得到很多小文件不能有效利用HDFS塊。這是查看的一個原因Hadoop Archives

+0

爲什麼「cut -f 2」而不是「貓」? – dranxo

+2

映射器的輸入是一個鍵和一個由製表符分隔的值。關鍵是文件中行的字節偏移量,值是行的文本。 'cut -f 2'只輸出數值。 –

+0

我如何壓縮hdfs中的文件夾? – subhashlg26

3

來自Jeff Wu的流式命令以及壓縮文件的串聯將給出單個壓縮文件。當一個非java映射器被傳遞給流式作業,並且輸入格式爲文本流式輸出時,只輸出值而不輸出密鑰。

hadoop jar contrib/streaming/hadoop-streaming-1.0.3.jar \ 
      -Dmapred.reduce.tasks=0 \ 
      -Dmapred.output.compress=true \ 
      -Dmapred.compress.map.output=true \ 
      -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \ 
      -input filename \ 
      -output /filename \ 
      -mapper /bin/cat \ 
      -inputformat org.apache.hadoop.mapred.TextInputFormat \ 
      -outputformat org.apache.hadoop.mapred.TextOutputFormat 
hadoop fs -cat /path/part* | hadoop fs -put - /path/compressed.gz 
+0

只是想確保我理解這些命令。第一個產生gzip文件的輸出,但實際文件不是* .gz格式,所以第二個命令是重命名它? – nevets1219

+0

不,第一個命令生成壓縮的* .gz **部分**文件(其中很多)。第二個命令是將這些部分文件連接成一個'compressed.gz'文件。 – daemon12

+0

上面的命令在壓縮輸出的每一行的末尾提供了額外的'tab'字符 – daemon12

3

這是我用過的:

/* 
* Pig script to compress a directory 
* input: hdfs input directory to compress 
*   hdfs output directory 
* 
* 
*/ 

set output.compression.enabled true; 
set output.compression.codec org.apache.hadoop.io.compress.BZip2Codec; 

--comma seperated list of hdfs directories to compress 
input0 = LOAD '$IN_DIR' USING PigStorage(); 

--single output directory 
STORE input0 INTO '$OUT_DIR' USING PigStorage(); 

雖然它不是LZO所以它可能是有點慢。

+0

這會壓縮輸入目錄中的每個單獨文件,還是壓縮將所有文件視爲一個大文件並對其進行壓縮,然後進行輸出很少的文件?如果是後一種情況,是否有一種方法可以指定每次應該嘗試壓縮多少數據,例如,一次3Gb? – AatG

+0

是的,它會將整個輸入目錄加載到一個別名中,並輸出爲$ {OUT_DIR}/part-m - *。bz2。如果你想要一個3Gb輸入目錄然後控制IN_DIR – dranxo

4

@Chitra 我不能因信譽問題發表評論

這裏的一切都在一個命令:在使用第二個命令相反的,你可以減少成一個壓縮文件直接

hadoop jar share/hadoop/tools/lib/hadoop-streaming-2.7.3.jar \ 
     -Dmapred.reduce.tasks=1 \ 
     -Dmapred.output.compress=true \ 
     -Dmapred.compress.map.output=true \ 
     -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.BZip2Codec \ 
     -input /input/raw_file \ 
     -output /archives/ \ 
     -mapper /bin/cat \ 
     -reducer /bin/cat \ 
     -inputformat org.apache.hadoop.mapred.TextInputFormat \ 
     -outputformat org.apache.hadoop.mapred.TextOutputFormat 

因此,你通過只有一個壓縮文件獲得大量空間

例如,假設我有4個10MB的文件(純文本,JSON格式)

該地圖只給我4個文件的650 KB 如果我映射和減少我有1.05 MB的文件