天天看點

hadoop 壓縮

原文位址:http://www.cnblogs.com/ggjucheng/archive/2012/04/22/2465580.html

hadoop對于壓縮檔案的支援

hadoop對于壓縮格式的是透明識别,我們的MapReduce任務的執行是透明的,hadoop能夠自動為我們 将壓縮的檔案解壓,而不用我們去關心。

如果我們壓縮的檔案有相應壓縮格式的擴充名(比如lzo,gz,bzip2等),hadoop就會根據擴充名去選擇×××解壓。

hadoop對每個壓縮格式的支援,詳細見下表:

壓縮格式 工具 算法 檔案擴充名 多檔案 可分割性
DEFLATE .deflate
gzip .gz
ZIP zip .zip 是,在檔案範圍内
bzip2 .bz2
LZO lzop .lzo

如果壓縮的檔案沒有擴充名,則需 要在執行mapreduce任務的時候指定輸入格式.

hadoop jar /usr/home/hadoop/hadoop-0.20.2/contrib/streaming/hadoop-streaming-0.20.2-CD H3B4.jar -file /usr/home/hadoop/hello/mapper.py -mapper /usr/home/hadoop/hello/mapper.py -file /usr/home/hadoop/hello/reducer.py -reducer /usr/home/hadoop/hello/reducer.py -input lzotest -output result4 -jobconf mapred.reduce.tasks=1 *-inputformat org.apache.hadoop.mapred.LzoTextInputFormat*       

hadoop下各種壓縮算法的壓縮比,壓縮時間,解壓時間見下表:

壓縮算法 原始檔案大小 壓縮後的檔案大小 壓縮速度 解壓縮速度
gzip   8.3GB   1.8GB 17.5MB/s 58MB/s
8.3GB 1.1GB 2.4MB/s 9.5MB/s
LZO-bset 2GB 4MB/s 60.6MB/s
2.9GB 49.3MB/S 74.6MB/s

hadoop各種壓縮算法的優缺點簡述

在考慮如何壓縮那些将由MapReduce處理的資料時,考慮壓縮格式是否支援分割是很重要的。考慮存儲在HDFS中的未壓縮的檔案,其大小為1GB,HDFS的塊大小為64MB,是以該檔案将被存儲為16塊,将此檔案用作輸入的MapReduce作業會建立1個輸人分片(split ,也稱為“分塊”。對于block,我們統一稱為“塊”。)每個分片都被作為一個獨立map任務的輸入單獨進行處理。

現在假設。該檔案是一個gzip格式的壓縮檔案,壓縮後的大小為1GB。和前面一樣,HDFS将此檔案存儲為16塊。然而,針對每一塊建立一個分塊是沒有用的,因為不可能從gzip資料流中的任意點開始讀取,map任務也不可能獨立于其他分塊隻讀取一個分塊中的資料。gzip格式使用DEFLATE來存儲壓縮過的資料,DEFLATE将資料作為一系列壓縮過的塊進行存儲。問題是,每塊的開始沒有指定使用者在資料流中任意點定位到下一個塊的起始位置,而是其自身與資料流同步。是以,gzip不支援分割(塊)機制。

在這種情況下,MapReduce不分割gzip格式的檔案,因為它知道輸入是gzip壓縮格式的(通過檔案擴充名得知),而gzip壓縮機制不支援分割機制。這樣是以犧牲本地化為代價:一個map任務将處理16個HDFS塊。大都不是map的本地資料。與此同時,因為map任務少,是以作業分割的粒度不夠細,進而導緻運作時間變長。

在我們假設的例子中,如果是一個LZO格式的檔案,我們會碰到同樣的問題,因為基本壓縮格式不為reader提供方法使其與流同步。但是,bzip2格式的壓縮檔案确實提供了塊與塊之間的同步标記(一個48位的PI近似值),是以它支援分割機制。

對于檔案的收集,這些問題會稍有不同。ZIP是存檔格式,是以它可以将多個檔案合并為一個ZIP檔案。每個檔案單獨壓縮,所有文檔的存儲位置存儲在ZIP檔案的尾部。這個屬性表明ZIP檔案支援檔案邊界處分割,每個分片中包括ZIP壓縮檔案中的一個或多個檔案。

在MapReduce我們應該使用哪種壓縮格式

根據應用的具體情況來決定應該使用哪種壓縮格式。就個人而言,更趨向于使用最快的速度壓縮,還是使用最優的空間壓縮?一般來說,應該嘗試不同的政策,并用具有代表性的資料集進行測試,進而找到最佳方法。對于那些大型的、沒有邊界的檔案,如日志檔案,有以下選項。

存儲未壓縮的檔案。

使用支援分割機制的壓縮格式,如bzip2。

在應用中将檔案分割成幾個大的資料塊,然後使用任何一種支援的壓縮格式單獨壓縮每個資料塊(可不用考慮壓縮格式是否支援分割)。在這裡,需要選擇資料塊的大小使壓縮後的資料塊在大小上相當于HDFS的塊。

使用支援壓縮和分割的Sequence File(序列檔案)。

對于大型檔案,不要對整個檔案使用不支援分割的壓縮格式,因為這樣會損失本地性優勢,進而使降低MapReduce應用的性能。

hadoop支援Splittable壓縮lzo

在hadoop中使用lzo的壓縮算法可以減小資料的大小和資料的磁盤讀寫時間,在HDFS中存儲壓縮資料,可以使叢集能儲存更多的資料,延長叢集的使用壽命。不僅如此,由于mapreduce作業通常瓶頸都在IO上,存儲壓縮資料就意味這更少的IO操作,job運作更加的高效。

但是在hadoop上使用壓縮也有兩個比較麻煩的地方:第一,有些壓縮格式不能被分塊,并行的處理,比如gzip。第二,另外的一些壓縮格式雖然支援分塊處理,但是解壓的過程非常的緩慢,使job的瓶頸轉移到了cpu上,例如bzip2。

如果能夠擁有一種壓縮算法,即能夠被分塊,并行的處理,速度也非常的快,那就非常的理想。這種方式就是lzo。

lzo的壓縮檔案是由許多的小的blocks組成(約256K),使的hadoop的job可以根據block的劃分來split job。不僅如此,lzo在設計時就考慮到了效率問題,它的解壓速度是gzip的兩倍,這就讓它能夠節省很多的磁盤讀寫,它的壓縮比的不如gzip,大約壓縮出來的檔案比gzip壓縮的大一半,但是這樣仍然比沒有經過壓縮的檔案要節省20%-50%的存儲空間,這樣就可以在效率上大大的提高job執行的速度。

hadoop下lzo配置文檔參考http://www.tech126.com/hadoop-lzo/

如何在MapReduce中使用壓縮

1.輸入的檔案的壓縮

如果輸入的檔案是壓縮過的,那麼在被MapReduce讀取時,它們會被自動解壓,根據檔案擴充名來決定應該使用哪一個壓縮×××。

2.MapReduce作業的輸出的壓縮

如果要壓縮MapReduce作業的輸出,請在作業配置檔案中将mapred.output.compress屬性設定為true。将mapred.output.compression.codec屬性設定為自己打算使用的壓縮編碼/×××的類名。

如果為輸出使用了一系列檔案,可以設定mapred.output.compression.type屬性來控制壓縮類型,預設為RECORD,它壓縮單獨的記錄。将它改為BLOCK,則可以壓縮一組記錄。由于它有更好的壓縮比,是以推薦使用。

3.map作業輸出結果的壓縮

即使MapReduce應用使用非壓縮的資料來讀取和寫入,我們也可以受益于壓縮map階段的中間輸出。因為map作業的輸出會被寫入磁盤并通過網絡傳輸到reducer節點,是以如果使用LZO之類的快速壓縮,能得到更好的性能,因為傳輸的資料量大大減少了。以下代碼顯示了啟用rnap輸出壓縮和設定壓縮格式的配置屬性。

conf.setCompressMapOutput(true);conf.setMapOutputCompressorClass(GzipCodec.class);      

本地壓縮庫

考慮到性能,最好使用一個本地庫(native library)來壓縮和解壓。例如,在一個測試中,使用本地gzip壓縮庫減少了解壓時間50%,壓縮時間大約減少了10%(與内置的Java實作相比較)。表4-4展示了Java和本地提供的每個壓縮格式的實作。井不是所有的格式都有本地實作(例如bzip2壓縮),而另一些則僅有本地實作(例如LZO)。

Java實作 本地實作

Hadoop帶有預置的32位和64位Linux的本地壓縮庫,位于庫/本地目錄。對于其他平台,需要自己編譯庫,具體請參見Hadoop的維基百科http://wiki.apache.org/hadoop/NativeHadoop。

本地庫通過Java系統屬性java.library.path來使用。Hadoop的腳本在bin目錄中已經設定好這個屬性,但如果不使用該腳本,則需要在應用中設定屬性。

繼續閱讀