Hadoop有一些數(shù)據(jù)I/O方面操作的工具欢摄,其中一些比Hadoop使用的都更普遍。例如數(shù)據(jù)完整性和壓縮笋粟。但是當(dāng)使用這些工具處理多達(dá)幾TB數(shù)據(jù)的時(shí)候怀挠,仍然需要特別注意。其它的一些工具或APIs構(gòu)建成了模塊用于開(kāi)發(fā)分布式系統(tǒng)害捕,例如:序列化框架和硬盤(pán)上的數(shù)據(jù)結(jié)構(gòu)化绿淋。
數(shù)據(jù)完整性
Hadoop的使用者肯定都希望數(shù)據(jù)在存儲(chǔ)或處理的過(guò)程中不會(huì)丟失或損壞。然而尝盼,由于硬盤(pán)或網(wǎng)絡(luò)的每一次I/O操作都有可能在讀或?qū)懙倪^(guò)程中出錯(cuò)吞滞,Hadoop經(jīng)常處理的數(shù)據(jù)量都相當(dāng)大,當(dāng)這樣地大量數(shù)據(jù)在系統(tǒng)中傳輸時(shí)盾沫,數(shù)據(jù)損壞的概率還是挺高的裁赠。
通常用于判斷數(shù)據(jù)是否損壞所使用的方法是當(dāng)數(shù)據(jù)第一次進(jìn)入系統(tǒng)時(shí)候計(jì)算一個(gè)校驗(yàn)和,并不管在任何時(shí)候赴精,數(shù)據(jù)被傳輸通過(guò)一個(gè)不可信的通道后佩捞,再一次計(jì)算校驗(yàn)和,就可以判斷數(shù)據(jù)是否損壞蕾哟。如果新生成的校驗(yàn)和與原始的校驗(yàn)和不一樣一忱,就認(rèn)為數(shù)據(jù)遭到了損壞。這個(gè)技術(shù)不能夠修復(fù)數(shù)據(jù)谭确,僅僅是檢查數(shù)據(jù)是否損壞帘营。(這也是不使用低檔的硬件的原因,特殊情況下琼富,肯定要使用ECC內(nèi)存)仪吧。注意:有時(shí)校驗(yàn)和也可能損壞,而數(shù)據(jù)沒(méi)有損壞鞠眉,但這種可能性很低薯鼠,因?yàn)樾r?yàn)和比數(shù)據(jù)小多了。
通常使用的錯(cuò)誤檢測(cè)碼是CRC-32(32位循環(huán)冗余校驗(yàn))械蹋,不管輸入的數(shù)據(jù)量多大出皇,都計(jì)算出一個(gè)32的整數(shù)校驗(yàn)和。CRC-32在Hadoop的ChecksumFileSystem類(lèi)中用于計(jì)算校驗(yàn)和哗戈。然而HDFS使用的是另一種更有效的方式郊艘,叫做CRC-32C。
HDFS中的數(shù)據(jù)完整性
HDFS透明地計(jì)算寫(xiě)入的所有數(shù)據(jù)的校驗(yàn)和,并且默認(rèn)情況下會(huì)在讀取數(shù)據(jù)時(shí)驗(yàn)證校驗(yàn)和纱注。每個(gè)用dfs.bytes-per-checksum屬性指定大小的數(shù)據(jù)塊都會(huì)單獨(dú)生成一個(gè)校驗(yàn)和畏浆。默認(rèn)是512字節(jié)。因?yàn)镃RC-32C校驗(yàn)和是4個(gè)字節(jié)狞贱,所以存儲(chǔ)開(kāi)銷(xiāo)少于1%刻获。((12810241024)/5124/12810241024)100%=0.78%。
數(shù)據(jù)節(jié)點(diǎn)有責(zé)任在接收到數(shù)據(jù)后存儲(chǔ)數(shù)據(jù)前校驗(yàn)數(shù)據(jù)瞎嬉,并計(jì)算校驗(yàn)和蝎毡,不管從客戶(hù)端接收數(shù)據(jù)還是在復(fù)制復(fù)本數(shù)據(jù)期間從其它節(jié)點(diǎn)接收數(shù)據(jù)。正在寫(xiě)入數(shù)據(jù)到HDFS的客戶(hù)端將校驗(yàn)和傳入數(shù)據(jù)節(jié)點(diǎn)的管道中(如第3章介紹的那樣)氧枣,管道中的最后一個(gè)數(shù)據(jù)節(jié)點(diǎn)驗(yàn)證校驗(yàn)和沐兵。如果數(shù)據(jù)節(jié)點(diǎn)檢測(cè)到錯(cuò)誤,客戶(hù)端會(huì)收到一個(gè)IOExcption子類(lèi)的異常便监,客戶(hù)端應(yīng)該采取應(yīng)用程序特定的措施扎谎,比如,重新嘗試寫(xiě)入茬贵。
當(dāng)客戶(hù)端從數(shù)據(jù)節(jié)點(diǎn)讀取數(shù)據(jù)的時(shí)候簿透,它們也要驗(yàn)證校驗(yàn)和移袍,將讀取的數(shù)據(jù)計(jì)算出的校驗(yàn)和和存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)中的校驗(yàn)和進(jìn)行比較解藻。每一個(gè)數(shù)據(jù)節(jié)點(diǎn)都永久保存了一份驗(yàn)證校驗(yàn)和的歷史日志。所以HDFS知道每一個(gè)數(shù)據(jù)塊最近驗(yàn)證校驗(yàn)和的時(shí)間葡盗。當(dāng)客戶(hù)端成功地校驗(yàn)了某一塊數(shù)據(jù)的時(shí)候螟左,它會(huì)告訴數(shù)據(jù)節(jié)點(diǎn),數(shù)據(jù)節(jié)點(diǎn)會(huì)更新日志觅够。保存這些校驗(yàn)的信息可以用于檢測(cè)壞的硬盤(pán)胶背。
除了客戶(hù)端讀取數(shù)據(jù)時(shí)的塊校驗(yàn),每一個(gè)數(shù)據(jù)節(jié)點(diǎn)都會(huì)以一個(gè)后臺(tái)線(xiàn)程方式執(zhí)行一個(gè)DataBlockScanner,周期性檢測(cè)存儲(chǔ)在這個(gè)數(shù)據(jù)節(jié)點(diǎn)上的數(shù)據(jù)塊是否損壞喘先。這是為了防止由于物理存儲(chǔ)媒介的"位衰減"造成的數(shù)據(jù)損壞钳吟。可以看第11章的"數(shù)據(jù)節(jié)點(diǎn)塊掃描"相關(guān)內(nèi)容詳細(xì)了解如何獲取掃描的報(bào)告窘拯。
由于HDFS存儲(chǔ)著數(shù)據(jù)塊的復(fù)本红且,所以它能夠通過(guò)復(fù)制一個(gè)好的復(fù)本生成一個(gè)新的,沒(méi)有損壞的復(fù)本來(lái)修復(fù)已經(jīng)損壞的塊涤姊。具體實(shí)現(xiàn)方法是客戶(hù)端在讀取塊數(shù)據(jù)時(shí)如果檢測(cè)到一個(gè)錯(cuò)誤暇番,它會(huì)向名稱(chēng)節(jié)點(diǎn)報(bào)告這個(gè)壞的塊和塊所在的數(shù)據(jù)節(jié)點(diǎn),然后拋出一個(gè)ChecksumException異常思喊。名稱(chēng)節(jié)點(diǎn)會(huì)將這個(gè)塊狀態(tài)標(biāo)記為"損壞"壁酬,并不再將其它客戶(hù)端提供這個(gè)塊的地址,然后在另外一個(gè)數(shù)據(jù)節(jié)點(diǎn)中生成這個(gè)塊的一個(gè)復(fù)本,直到達(dá)到設(shè)置的塊復(fù)本數(shù)舆乔,一旦完成后岳服,這個(gè)損壞的塊就會(huì)被刪除。
我們可以在調(diào)用FileSystem的open方法打開(kāi)文件之前希俩,調(diào)用它的setVerifyChecksum方法派阱,傳遞一個(gè)false值,就可以關(guān)閉校驗(yàn)和的驗(yàn)證斜纪。如果使用shell命令贫母,我們可以在-get或-copyToLocal命令中添加-ignoreCrc選項(xiàng)同樣可以關(guān)閉校驗(yàn)和的驗(yàn)證。如果你想要看看這部分損壞的數(shù)據(jù)盒刚,再進(jìn)行相應(yīng)處理的話(huà)瘤运,這個(gè)功能將是有用的键痛。例如,你也許想在刪除損壞的塊數(shù)據(jù)之前想要看看是否能夠恢復(fù)塊中的數(shù)據(jù)。
你可以通過(guò)使用hadoop fs -checksum來(lái)得到一個(gè)文件的校驗(yàn)和柄驻。這對(duì)于檢查HDFS中兩個(gè)文件是否有相同的內(nèi)容是有用的(distcp命令也可以做這些事情),可以參看"使用distcp命令并發(fā)復(fù)制"小節(jié)舉的示例猩系。
LocalFileSystem
Hadoop LocalFileSystem在客戶(hù)端驗(yàn)證校驗(yàn)和绍申。這意味著當(dāng)你向一個(gè)叫"filename"的文件中寫(xiě)入數(shù)據(jù)時(shí),文件系統(tǒng)客戶(hù)端會(huì)在文件相同目錄透明的創(chuàng)建一個(gè)隱藏的文件吩愧,叫做 .filename.crc芋酌,這個(gè)文件包含每一段文件數(shù)據(jù)的檢驗(yàn)和。段的大小由屬性file.bytes-per-checksum定義雁佳,默認(rèn)是512字節(jié)脐帝。段大小做為元數(shù)據(jù)存儲(chǔ)在.crc后綴的文件中,所以即使段大小的設(shè)置以后改變了糖权,文件仍然可以完好無(wú)損地讀取堵腹。當(dāng)讀取文件時(shí),會(huì)驗(yàn)證檢驗(yàn)和星澳,如果出現(xiàn)錯(cuò)誤疚顷,LocalFileSystem拋出ChecksumException異常。
計(jì)算校驗(yàn)和的代價(jià)很小(JAVA中禁偎,使用native代碼計(jì)算)腿堤,不會(huì)對(duì)讀取或?qū)懭胛募斐墒裁从绊憽?duì)于大多數(shù)應(yīng)用來(lái)說(shuō)届垫,為了保證數(shù)據(jù)的完整性這是完全可以承受的代價(jià)释液。然而,如果底層的文件系統(tǒng)本身支持校驗(yàn)装处,就可以關(guān)閉LocalFileSystem的校驗(yàn)误债。此時(shí)可以使用RawLocalFileSysem代替LocalFileSystem浸船。要想在應(yīng)用的全局范圍內(nèi)關(guān)閉校驗(yàn)和,可以將屬性fs.file.impl的值設(shè)置為org.apache.hadoop.fs.RawLocalFileSystem寝蹈。如果你僅僅想對(duì)某一些讀取操作關(guān)閉檢驗(yàn)和驗(yàn)證時(shí)李命,也可以直接創(chuàng)建一個(gè)RawLocalFileSystem實(shí)例。例如:
Configuration conf = ...
FileSystem fs = new RawLocalFileSystem();
fs.initialize(null, conf);
ChecksumFileSystem
LocalFileSystem使用CheckFileSystem來(lái)實(shí)現(xiàn)校驗(yàn)和的功能箫老。這個(gè)類(lèi)可以很方便地在其它沒(méi)有校驗(yàn)和功能的文件系統(tǒng)中加入校驗(yàn)和功能封字。ChecksumFileSystem僅僅是FileSystem的一個(gè)封裝類(lèi)。一般的寫(xiě)法如下:
FileSystem rawFs = ...
FileSystem checksummedFs = new ChecksumFileSystem(rawFs);
底層的文件系統(tǒng)叫做原生文件系統(tǒng)耍鬓,可以通過(guò)ChecksumFileSystem的getRawFileSystem方法獲得阔籽。ChecksumFileSystem還有一些和校驗(yàn)和相關(guān)的有用的方法,例如getChecksumFile()方法用于獲取任意文件的校驗(yàn)和文件的路徑牲蜀“手疲可以查看相關(guān)參考資料看看其它的方法。
如果在讀取文件的過(guò)程中涣达,ChecksumFileSystem檢測(cè)到一個(gè)錯(cuò)誤在辆。它將會(huì)調(diào)用它的reportChecksumFailure()方法。這個(gè)方法默認(rèn)的實(shí)現(xiàn)沒(méi)有做任何事情度苔。但是LocalFileSystem將檢驗(yàn)失敗的文件和它的校驗(yàn)和單獨(dú)移到同一設(shè)備中叫做"bad_files"的目錄中匆篓。管理員應(yīng)該定期地檢查這個(gè)目錄中是否有壞的文件并處理。
壓縮
文件壓縮有兩個(gè)主要的好處:減少存儲(chǔ)文件所需的空間;加快數(shù)據(jù)在網(wǎng)絡(luò)傳輸?shù)乃俾屎蛷挠脖P(pán)讀寫(xiě)文件的速度寇窑。當(dāng)處理海量數(shù)據(jù)時(shí)鸦概,這些好處帶來(lái)的效果是很可觀的,所以它值得我們仔細(xì)考慮如何在Hadoop使用壓縮疗认。
有多種不同的壓縮格式完残,工具和算法。每一種都有不同的特性横漏。表5-1例舉出了Hadoop常用的一些壓縮工具/格式。
壓縮格式 | 工具 | 算法 | 文件擴(kuò)展名 | 可切片? |
---|---|---|---|---|
DEFLATE[1] | N/A | DEFLATE | .deflate | No |
gzip | gzip | DEFLATE | .gz | No |
bzip2 | bzip2 | bzip2 | .bz2 | Yes |
LZO | lzop | LZO | .lzo | No[2] |
LZ4 | N/A | LZ4 | .lz4 | No |
Snappy | N/A | Snappy | .snappy | No |
所有的壓縮算法都會(huì)在空間與時(shí)間兩方面進(jìn)行權(quán)衡:更快地壓縮與解壓縮算法通常以節(jié)約更小的空間為代價(jià)熟掂。表5-1所列的壓縮工具一般都會(huì)提供9個(gè)不同的選擇來(lái)在空間與時(shí)間上進(jìn)行權(quán)衡缎浇。-1意思是優(yōu)化速度,-9意思是優(yōu)化空間赴肚。例如下面的命令以最快的壓縮速度創(chuàng)建了一個(gè)叫做file.gz的壓縮文件素跺。
% gzip -1 file
不同的壓縮工具有著非常不同的壓縮特性。通常選擇gzip壓縮格式誉券,所有壓縮工具中指厌,gzip在空間與時(shí)間權(quán)衡方面性能居中。bzip2比gzip有更高的壓縮率踊跟,但是更慢踩验。bzip2的解壓速度比它的壓縮速度快,但是還是比其它壓縮格式要慢。另一方面箕憾,LZO牡借、LZ4和Snappy都優(yōu)化了速度,在速度上按照順序依次更快袭异,且都比gzip快很多钠龙。但是壓縮率不如gzip高。Snappy和LZ4比LZO的解壓速度要快很多[3]御铃。
表5-1的"可切片"一列表示壓縮格式是否支持切片(也就是說(shuō)你可以定位到數(shù)據(jù)流的任意一點(diǎn)碴里,并從這一點(diǎn)開(kāi)始讀取數(shù)據(jù))∩险妫可切片的壓縮格式特別適合MapReduce并闲。可以看稍后的"壓縮與切片"小節(jié)進(jìn)一步討論谷羞。
編解碼器
編解碼器是壓縮-解壓算法的實(shí)現(xiàn)帝火。Hadoop中,一個(gè)編解碼器是CompressionCodec接口的一個(gè)實(shí)現(xiàn)類(lèi)湃缎。例如:GzipCodec封裝了gzip的壓縮與解壓算法犀填。表5-2列舉出了Hadoop中的編解碼器。
壓縮格式 | Hadoop CompressCodec |
---|---|
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
gzip | org.apache.hadoop.io.compress.GzipCodec |
bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
LZ4 | org.apache.hadoop.io.compress.Lz4Codec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
LZO庫(kù)是遵循GPL協(xié)議的嗓违,所以在Apache發(fā)布的Hadoop中也許沒(méi)有包含九巡,所以需要單獨(dú)從Google(或GitHub,包含bug修復(fù)和更多工具)下載。
LzopCodec是一個(gè)兼容lzop工具的實(shí)現(xiàn)類(lèi)蹂季,本質(zhì)上冕广,是帶有額外頭文件的LZO壓縮工具類(lèi)。也有一個(gè)純LZO壓縮格式的實(shí)現(xiàn)類(lèi)叫做LzoCodec,它使用的是.lzo_deflate文件擴(kuò)展名(就如同DEFLATE偿洁,是一個(gè)沒(méi)有頭文件的gzip)撒汉。
使用CompressionCodec壓縮與解壓流
CompressionCodec有兩個(gè)方法,可以讓你很容易的壓縮或解壓數(shù)據(jù)涕滋。為了在寫(xiě)入輸出流時(shí)壓縮數(shù)據(jù)睬辐,你可以使用createOutputStream(OutputStream out)方法創(chuàng)建一個(gè)CompressionOutputStream輸出流,然后你將未壓縮的數(shù)據(jù)寫(xiě)入宾肺,CompressionOutputStream就可以讓數(shù)據(jù)以壓縮的形式寫(xiě)入底層輸出流中溯饵。相應(yīng)地,要想從一個(gè)輸入流中解壓數(shù)據(jù)锨用,調(diào)用createInputStream(InpuStream in)方法獲取一個(gè)CompressionInputStream對(duì)象丰刊,這個(gè)對(duì)象可以讓你從底層流的壓縮數(shù)據(jù)中讀取出解壓后的數(shù)據(jù)。
CompressionOutputStream和CompressionInputStream與java.util.zip.DeflaterOutputStream和java.util.zip.DeflaterInputStream相似增拥。不過(guò)啄巧,前兩者比后兩者多個(gè)功能寻歧,可以重置底層的壓縮或解壓器。這對(duì)于想分塊壓縮數(shù)據(jù)的應(yīng)用來(lái)說(shuō)是很重要的棵帽。例如本章后面將講解的SequenceFile熄求。
示例5-1展示了如何將從標(biāo)準(zhǔn)輸入流讀取的數(shù)據(jù)壓縮,然后寫(xiě)入標(biāo)準(zhǔn)輸出流中逗概。
示例5-1:壓縮讀取的數(shù)據(jù)并寫(xiě)入標(biāo)準(zhǔn)輸出流的程序
public class StreamCompressor {
public static void main(String[] args) throws Exception {
String codecClassname = args[0];
Class<?> codecClass = Class.forName(codecClassname);
Configuration conf = new Configuration();
CompressionCodec codec = (CompressionCodec)
ReflectionUtils.newInstance(codecClass, conf);
CompressionOutputStream out = codec.createOutputStream(System.out);
IOUtils.copyBytes(System.in, out, 4096, false);
out.finish();
}
}
這個(gè)應(yīng)用需要一個(gè) CompressionCodec實(shí)現(xiàn)類(lèi)的全類(lèi)名做為命令行第一個(gè)參數(shù)弟晚。我們使用ReflectionUtils創(chuàng)建一個(gè)編碼類(lèi)的實(shí)例,然后獲取一個(gè)System.out的壓縮封裝類(lèi)逾苫,然后我們調(diào)用IOUtils的copyBytes方法將輸入流中的數(shù)據(jù)復(fù)制到輸出流中卿城。在輸出之前,數(shù)據(jù)會(huì)經(jīng)過(guò) CompressionOutputStream壓縮铅搓。最后調(diào)用 CompressionOutputStream的finish方法告訴壓縮器停止向輸出流中寫(xiě)入壓縮的數(shù)據(jù)瑟押,但不關(guān)閉輸出流。我們可以用下面的命令進(jìn)行嘗試星掰,壓縮"Text"字符串多望,調(diào)用StreamCompressor類(lèi),傳入 GzipCodec壓縮器氢烘,然后用gunzip進(jìn)行解壓怀偷。
% echo "Text" | hadoop StreamCompressor org.apache.hadoop.io.compress.GzipCodec \
| gunzip -
Text
使用CompressionCodecFactory推斷出壓縮編碼
如果你需要讀取一個(gè)壓縮文件,正常情況下你會(huì)觀察壓縮文件的擴(kuò)展名來(lái)推斷出所使用的壓縮編碼播玖,.gz結(jié)尾的文件可以使用 GzipCodec讀取等等椎工。每一種壓縮編碼的擴(kuò)展名都在表5-1中列舉。CompressionCodecFactory通過(guò)它的getCodec()方法提供了一種通過(guò)擴(kuò)展名得到相應(yīng)壓縮編碼的方法蜀踏。示例5-2顯示了如何使用這種方法解壓文件维蒙。
示例:5-2 從文件擴(kuò)展名推斷出解壓縮編碼來(lái)對(duì)文件進(jìn)行解壓的程序
public class FileDecompressor {
public static void main(String[] args) throws Exception {
String uri = args[0];
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
Path inputPath = new Path(uri);
CompressionCodecFactory factory = new CompressionCodecFactory(conf);
CompressionCodec codec = factory.getCodec(inputPath);
if (codec == null) {
System.err.println("No codec found for " + uri);
System.exit(1);
}
String outputUri =
CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension());
InputStream in = null;
OutputStream out = null;
try {
in = codec.createInputStream(fs.open(inputPath));
out = fs.create(new Path(outputUri));
IOUtils.copyBytes(in, out, conf);
} finally {
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
}
}
一旦推斷出了編碼,就會(huì)使用 CompressionCodecFactory的 removeSuffix() 靜態(tài)方法去掉文件的后綴得到輸出文件名果覆。通過(guò)這種方法颅痊,使用如下命令,一個(gè)叫做file.gz的文件會(huì)被解壓成file随静。
% hadoop FileDecompressor file.gz
CompressionCodecFactory會(huì)加載表5-2中除了LZO之外的所有編碼八千,和表5-3中屬性 io.compression.codecs所列舉的所有編碼,默認(rèn)情況下燎猛,這個(gè)屬性值為空,如果你希望注冊(cè)一個(gè)自定義的編碼(例如這個(gè)外部的LZO編碼)照皆,你就需要修改這個(gè)屬性重绷。每一種編碼都知道它自己的默認(rèn)文件擴(kuò)展名,因此CompressionCodecFactory就可以通過(guò)搜索所有注冊(cè)的編碼找到與給定文件名匹配的編碼膜毁。
表5-3:壓縮編碼配置屬性
屬性名 | 類(lèi)型 | 默認(rèn)值 | 描述 |
---|---|---|---|
io.compression.codecs | 逗號(hào)分隔的類(lèi)名 | 外部的 CompressionCodec壓縮與解壓縮類(lèi)列表 |
本地庫(kù)
從性能考慮昭卓,推薦使用本地庫(kù)來(lái)進(jìn)行壓縮與解壓縮愤钾。例如一項(xiàng)測(cè)試表明,使用本地庫(kù)中的gzip比使用java內(nèi)建的gzip實(shí)現(xiàn)至多減少50%解壓縮時(shí)間和大約10%的壓縮時(shí)間候醒。表5-4顯示了對(duì)于所有壓縮格式能颁,java與本地庫(kù)是否提供了實(shí)現(xiàn)。所有的格式都有本地實(shí)現(xiàn)倒淫,但并不是都有java實(shí)現(xiàn)伙菊,例如LZO壓縮格式。
表5-4:壓縮庫(kù)實(shí)現(xiàn)
壓縮格式 | java實(shí)現(xiàn) | 本地庫(kù)實(shí)現(xiàn) |
---|---|---|
DEFLATE | Yes | Yes |
gzip | Yes | Yes |
bzip2 | Yes | Yes |
LZO | No | Yes |
LZ4 | No | Yes |
Snappy | No | Yes |
Apache Hadoop的二進(jìn)制tar包帶有預(yù)建的針對(duì)64位Linux系統(tǒng)的壓縮編碼本地庫(kù)實(shí)現(xiàn)敌土,叫做 libhadoop.so镜硕。對(duì)于其它平臺(tái),你需要按照Hadoop源碼頂級(jí)目錄中BUILDING.txt文件說(shuō)明的那樣編譯自己的庫(kù)文件返干。
通過(guò)設(shè)置java系統(tǒng)屬性 java.library.path可以找到本地庫(kù)兴枯,可以在hadoop的etc/hadoop目錄中進(jìn)行設(shè)置。如果你不想在hadoop配置文件中設(shè)置矩欠,你就需要在應(yīng)用程序中設(shè)置财剖。
默認(rèn)情況下,Hadoop會(huì)自動(dòng)尋找與它運(yùn)行平臺(tái)相對(duì)應(yīng)的本地庫(kù)癌淮,如果發(fā)現(xiàn)了躺坟,就會(huì)自動(dòng)加載。這就意味著你不需要為了使用本地庫(kù)而做任何配置该默。然后瞳氓,在某些情況下,你希望不使用本地庫(kù)栓袖,例如你想調(diào)度一個(gè)壓縮相關(guān)的問(wèn)題時(shí)。你可以通過(guò)將屬性io.native.lib.available設(shè)置成false來(lái)不使用本地庫(kù)裹刮,而使用Java內(nèi)建的編碼(如果可以找得到的話(huà))捧弃。
編碼池
如果你正在使用本地庫(kù)赠叼,而且在你的應(yīng)用程序中需要做大量的壓縮與解壓縮工作,可以考慮使用編碼池(CodecPool)违霞。編碼池可以讓你重用解壓縮對(duì)象,而省去了創(chuàng)建這些對(duì)象的開(kāi)銷(xiāo)涧郊。
示例5-3中的代碼顯示了編碼池的應(yīng)用。雖然本例實(shí)際上只需要?jiǎng)?chuàng)建一個(gè)解壓縮對(duì)象眼五,沒(méi)有必要使用編碼池妆艘。
示例5-3:從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù)彤灶,使用編碼池壓縮器將數(shù)據(jù)寫(xiě)入標(biāo)準(zhǔn)輸出中
public class PooledStreamCompressor {
public static void main(String[] args) throws Exception {
String codecClassname = args[0];
Class<?> codecClass = Class.forName(codecClassname);
Configuration conf = new Configuration();
CompressionCodec codec = (CompressionCodec)
ReflectionUtils.newInstance(codecClass, conf);
Compressor compressor = null;
try {
compressor = CodecPool.getCompressor(codec);
CompressionOutputStream out =
codec.createOutputStream(System.out, compressor);
IOUtils.copyBytes(System.in, out, 4096, false);
out.finish();
} finally {
CodecPool.returnCompressor(compressor);
}
}
}
對(duì)于給定的 CompressionCodec幌陕,我們可以從編碼池中獲取壓縮實(shí)例汽煮。然后在CompressionCodec的 createOutputStream() 方法中使用這個(gè)壓縮實(shí)例。通過(guò)使用finally塊搬卒,我們就可以確保翎卓,這個(gè)壓縮實(shí)例在使用完以后能夠回到編碼池中,即使在從標(biāo)準(zhǔn)輸入流復(fù)制數(shù)據(jù)到標(biāo)準(zhǔn)輸出流中時(shí)坯门,出現(xiàn)了IOException異常逗扒。
未完待續(xù).........
-
DEFLATE壓縮算法標(biāo)準(zhǔn)實(shí)現(xiàn)是zlib.但是沒(méi)有生成DEFLATE格式的通用命令行工具。通常使用gzip工具(gzip使用DEFLATE壓縮算法现恼,不過(guò)增加了額外的頭和尾)黍檩。.deflate格式的擴(kuò)展文件是Hadoop使用的。 ?
-
如果在預(yù)處理過(guò)程中喳逛,已經(jīng)創(chuàng)建了索引棵里,LZO壓縮的文件可以切片,見(jiàn)后面的壓縮的切片小節(jié)介紹典蝌。 ?
-
想了解更多綜合性壓縮標(biāo)準(zhǔn)头谜,可以參看jvm壓縮標(biāo)準(zhǔn)了解JVM兼容的一些庫(kù)(包庫(kù)一些native庫(kù)) ?