Hadoop在MapReduce中使用壓縮詳解
Hadoop對(duì)于壓縮文件的支持
如果我們壓縮的文件有相應(yīng)壓縮格式的擴(kuò)展名(比如lzo,gz,bzip2等),hadoop就會(huì)根據(jù)擴(kuò)展名去選擇解碼器解壓。
hadoop對(duì)每個(gè)壓縮格式的支持,詳細(xì)見下表:
如果壓縮的文件沒有擴(kuò)展名,則需 要在執(zhí)行mapreduce任務(wù)的時(shí)候指定輸入格式.
- 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下各種壓縮算法的壓縮比,壓縮時(shí)間,解壓時(shí)間見下表:
壓縮算法 | 原始文件大小 | 壓縮后的文件大小 | 壓縮速度 | 解壓縮速度 |
gzip | 8.3GB | 1.8GB | 17.5MB/s | 58MB/s |
bzip2 | 8.3GB | 1.1GB | 2.4MB/s | 9.5MB/s |
LZO-bset | 8.3GB | 2GB | 4MB/s | 60.6MB/s |
LZO | 8.3GB | 2.9GB | 49.3MB/S | 74.6MB/s |
hadoop各種壓縮算法的優(yōu)缺點(diǎn)簡(jiǎn)述
在考慮如何壓縮那些將由MapReduce處理的數(shù)據(jù)時(shí),考慮壓縮格式是否支持分割是很重要的??紤]存儲(chǔ)在HDFS中的未壓縮的文件,其大小為1GB,HDFS的塊大小為64MB,所以該文件將被存儲(chǔ)為16塊,將此文件用作輸入的MapReduce作業(yè)會(huì)創(chuàng)建1個(gè)輸人分片(split ,也稱為“分塊”。對(duì)于block,我們統(tǒng)一稱為“塊”。)每個(gè)分片都被作為一個(gè)獨(dú)立map任務(wù)的輸入單獨(dú)進(jìn)行處理。
現(xiàn)在假設(shè)。該文件是一個(gè)gzip格式的壓縮文件,壓縮后的大小為1GB。和前面一樣,HDFS將此文件存儲(chǔ)為16塊。然而,針對(duì)每一塊創(chuàng)建一個(gè)分塊是沒有用的,因?yàn)椴豢赡軓膅zip數(shù)據(jù)流中的任意點(diǎn)開始讀取,map任務(wù)也不可能獨(dú)立于其他分塊只讀取一個(gè)分塊中的數(shù)據(jù)。gzip格式使用DEFLATE來存儲(chǔ)壓縮過的數(shù)據(jù),DEFLATE將數(shù)據(jù)作為一系列壓縮過的塊進(jìn)行存儲(chǔ)。問題是,每塊的開始沒有指定用戶在數(shù)據(jù)流中任意點(diǎn)定位到下一個(gè)塊的起始位置,而是其自身與數(shù)據(jù)流同步。因此,gzip不支持分割(塊)機(jī)制。
在這種情況下,MapReduce不分割gzip格式的文件,因?yàn)樗垒斎胧莋zip壓縮格式的(通過文件擴(kuò)展名得知),而gzip壓縮機(jī)制不支持分割機(jī)制。這樣是以犧牲本地化為代價(jià):一個(gè)map任務(wù)將處理16個(gè)HDFS塊。大都不是map的本地?cái)?shù)據(jù)。與此同時(shí),因?yàn)閙ap任務(wù)少,所以作業(yè)分割的粒度不夠細(xì),從而導(dǎo)致運(yùn)行時(shí)間變長(zhǎng)。
在我們假設(shè)的例子中,如果是一個(gè)LZO格式的文件,我們會(huì)碰到同樣的問題,因?yàn)榛緣嚎s格式不為reader提供方法使其與流同步。但是,bzip2格式的壓縮文件確實(shí)提供了塊與塊之間的同步標(biāo)記(一個(gè)48位的PI近似值),因此它支持分割機(jī)制。
對(duì)于文件的收集,這些問題會(huì)稍有不同。ZIP是存檔格式,因此它可以將多個(gè)文件合并為一個(gè)ZIP文件。每個(gè)文件單獨(dú)壓縮,所有文檔的存儲(chǔ)位置存儲(chǔ)在ZIP文件的尾部。這個(gè)屬性表明ZIP文件支持文件邊界處分割,每個(gè)分片中包括ZIP壓縮文件中的一個(gè)或多個(gè)文件。
在MapReduce我們應(yīng)該使用哪種壓縮格式
根據(jù)應(yīng)用的具體情況來決定應(yīng)該使用哪種壓縮格式。就個(gè)人而言,更趨向于使用最快的速度壓縮,還是使用最優(yōu)的空間壓縮?一般來說,應(yīng)該嘗試不同的策略,并用具有代表性的數(shù)據(jù)集進(jìn)行測(cè)試,從而找到最佳方法。對(duì)于那些大型的、沒有邊界的文件,如日志文件,有以下選項(xiàng)。
存儲(chǔ)未壓縮的文件。
使用支持分割機(jī)制的壓縮格式,如bzip2。
在應(yīng)用中將文件分割成幾個(gè)大的數(shù)據(jù)塊,然后使用任何一種支持的壓縮格式單獨(dú)壓縮每個(gè)數(shù)據(jù)塊(可不用考慮壓縮格式是否支持分割)。在這里,需要選擇數(shù)據(jù)塊的大小使壓縮后的數(shù)據(jù)塊在大小上相當(dāng)于HDFS的塊。
使用支持壓縮和分割的Sequence File(序列文件)。
對(duì)于大型文件,不要對(duì)整個(gè)文件使用不支持分割的壓縮格式,因?yàn)檫@樣會(huì)損失本地性優(yōu)勢(shì),從而使降低MapReduce應(yīng)用的性能。
hadoop支持Splittable壓縮lzo
在hadoop中使用lzo的壓縮算法可以減小數(shù)據(jù)的大小和數(shù)據(jù)的磁盤讀寫時(shí)間,在HDFS中存儲(chǔ)壓縮數(shù)據(jù),可以使集群能保存更多的數(shù)據(jù),延長(zhǎng)集群的使用壽命。不僅如此,由于mapreduce作業(yè)通常瓶頸都在IO上,存儲(chǔ)壓縮數(shù)據(jù)就意味這更少的IO操作,job運(yùn)行更加的高效。
但是在hadoop上使用壓縮也有兩個(gè)比較麻煩的地方:第一,有些壓縮格式不能被分塊,并行的處理,比如gzip。第二,另外的一些壓縮格式雖然支持分塊處理,但是解壓的過程非常的緩慢,使job的瓶頸轉(zhuǎn)移到了cpu上,例如bzip2。
如果能夠擁有一種壓縮算法,即能夠被分塊,并行的處理,速度也非常的快,那就非常的理想。這種方式就是lzo。
lzo的壓縮文件是由許多的小的blocks組成(約256K),使的hadoop的job可以根據(jù)block的劃分來split job。不僅如此,lzo在設(shè)計(jì)時(shí)就考慮到了效率問題,它的解壓速度是gzip的兩倍,這就讓它能夠節(jié)省很多的磁盤讀寫,它的壓縮比的不如gzip,大約壓縮出來的文件比gzip壓縮的大一半,但是這樣仍然比沒有經(jīng)過壓縮的文件要節(jié)省20%-50%的存儲(chǔ)空間,這樣就可以在效率上大大的提高job執(zhí)行的速度。
hadoop下lzo配置文檔參考http://www.tech126.com/hadoop-lzo/
如何在MapReduce中使用壓縮
1.輸入的文件的壓縮
如果輸入的文件是壓縮過的,那么在被MapReduce讀取時(shí),它們會(huì)被自動(dòng)解壓,根據(jù)文件擴(kuò)展名來決定應(yīng)該使用哪一個(gè)壓縮解碼器。
2.MapReduce作業(yè)的輸出的壓縮
如果要壓縮MapReduce作業(yè)的輸出,請(qǐng)?jiān)谧鳂I(yè)配置文件中將mapred.output.compress屬性設(shè)置為true。將mapred.output.compression.codec屬性設(shè)置為自己打算使用的壓縮編碼/解碼器的類名。
如果為輸出使用了一系列文件,可以設(shè)置mapred.output.compression.type屬性來控制壓縮類型,默認(rèn)為RECORD,它壓縮單獨(dú)的記錄。將它改為BLOCK,則可以壓縮一組記錄。由于它有更好的壓縮比,所以推薦使用。
3.map作業(yè)輸出結(jié)果的壓縮
即使MapReduce應(yīng)用使用非壓縮的數(shù)據(jù)來讀取和寫入,我們也可以受益于壓縮map階段的中間輸出。因?yàn)閙ap作業(yè)的輸出會(huì)被寫入磁盤并通過網(wǎng)絡(luò)傳輸?shù)絩educer節(jié)點(diǎn),所以如果使用LZO之類的快速壓縮,能得到更好的性能,因?yàn)閭鬏數(shù)臄?shù)據(jù)量大大減少了。以下代碼顯示了啟用rnap輸出壓縮和設(shè)置壓縮格式的配置屬性。
- conf.setCompressMapOutput(true);
- conf.setMapOutputCompressorClass(GzipCodec.class);
本地壓縮庫
考慮到性能,最好使用一個(gè)本地庫(native library)來壓縮和解壓。例如,在一個(gè)測(cè)試中,使用本地gzip壓縮庫減少了解壓時(shí)間50%,壓縮時(shí)間大約減少了10%(與內(nèi)置的Java實(shí)現(xiàn)相比較)。表4-4展示了Java和本地提供的每個(gè)壓縮格式的實(shí)現(xiàn)。井不是所有的格式都有本地實(shí)現(xiàn)(例如bzip2壓縮),而另一些則僅有本地實(shí)現(xiàn)(例如LZO)。
壓縮格式 | Java實(shí)現(xiàn) | 本地實(shí)現(xiàn) |
DEFLATE | 是 | 是 |
gzip | 是 | 是 |
bzip2 | 是 | 否 |
LZO | 否 | 是 |
Hadoop帶有預(yù)置的32位和64位Linux的本地壓縮庫,位于庫/本地目錄。對(duì)于其他平臺(tái),需要自己編譯庫,具體請(qǐng)參見Hadoop的維基百科http://wiki.apache.org/hadoop/NativeHadoop。
本地庫通過Java系統(tǒng)屬性java.library.path來使用。Hadoop的腳本在bin目錄中已經(jīng)設(shè)置好這個(gè)屬性,但如果不使用該腳本,則需要在應(yīng)用中設(shè)置屬性。
默認(rèn)情況下,Hadoop會(huì)在它運(yùn)行的平臺(tái)上查找本地庫,如果發(fā)現(xiàn)就自動(dòng)加載。這意味著不必更改任何配置設(shè)置就可以使用本地庫。在某些情況下,可能希望禁用本地庫,比如在調(diào)試壓縮相關(guān)問題的時(shí)候。為此,將屬性hadoop.native.lib設(shè)置為false,即可確保內(nèi)置的Java等同內(nèi)置實(shí)現(xiàn)被使用(如果它們可用的話)。
原文鏈接:http://www.cnblogs.com/ggjucheng/archive/2012/04/22/2465580.html
【編輯推薦】
- Apache .htaccess文件的8個(gè)用法
- Hadoop 從Yahoo向Google的技術(shù)轉(zhuǎn)折
- Hadoop集群與Hadoop性能優(yōu)化
- Facebook實(shí)時(shí)信息系統(tǒng):HBase每月存儲(chǔ)1350億條信息