Hadoop中的壓縮與解壓縮案例詳解

壓縮主要關註點:壓縮率,壓縮速度,解壓速度,是否可切片

一:壓縮的作用

壓縮技術能夠減少底層HDFS讀寫字節數,減少磁盤IO,提升網絡傳輸效率,因為磁盤IO和網絡帶寬是Hadoop的寶貴資源;特別是在運行MR程序時,I/O,網絡數據傳輸,shuffle及Merge都要花大量的時間,因此壓縮非常重要; 壓縮是提升Hadoop運行效率的一種優化策略,使用得當可以提升效率,但是使用不當也可能降低效率

1.1:壓縮的原則:

1、計算(運算)密集型任務:大量使用CPU去做數學運算,此時少用壓縮
2、IO密集型任務:此時多用壓縮         壓縮需要消耗CPU資源

1.2:MR支持的壓縮編碼

DEFLATE                                                不支持切分

Gzip                                                         不支持切分

bzip2                                                         支持切分

LZO                非hadoop自帶 安裝           支持切分

Snappy                                                    不支持切分

為瞭支持多種壓縮/解壓縮算法,Hadoop引入瞭編碼/解碼器

  • org.apache.hadoop.io.compress.DefaultCodec
  • org.apache.hadoop.io.compress.GzipCodec
  • org.apache.hadoop.io.compress.BZip2Codec
  • com.hadoop.compression.lzo.LzopCodec
  • org.apache.hadoop.io.compress.SnappyCodec

1.3:壓縮性能的比較

1.4:壓縮方式的選擇

1.4.1Gzip壓縮

優點:壓縮/解壓縮比較快,處理Gzip格式文件和直接處理文本一樣

缺點:不支持split

應用場景:

        當每個文件壓縮之後在130M以內(1個塊大小內),考慮。

1.4.2:Bzip2壓縮

優點:比Gzip壓縮率高,支持split

缺點:壓縮/解壓速度慢

應用場景:適合對速度要求不高,但需要較高的壓縮率  

                   或者輸出數據比較大,處理之後的數據需要壓縮存檔,同時對單個很大的文本文件像壓縮減少存儲空間,同時需支持split;

1.4.3LZO壓縮

優點:壓縮/解壓縮比較快,合理的壓縮率,支持split,是Hadoop最流行的壓縮格式,在Linux系統下需要安裝

缺點:壓縮率比Gzip低一些,Hadoop本身不支持,為瞭支持split需要建立索引,還需要指定InputFormat為Lzo格式

應用場景:一個很大的文本文件,壓縮之後還大於200M以上可以考慮,而且單個文件越大,LZO優點越明顯;

1.4.4Snappy壓縮

優點: 壓縮速度和合理的壓縮率

缺點:不支持split,壓縮率比gzip低,Hadoop本身不支持需要安裝

應用場景:當MapReduce作業的Map輸出的數據比較大的時候,作為Map到Reduce的 中間數據的壓縮格式,或者作為一個MapReduce作業的輸出和另外一個MapReduce作業的輸入。

壓縮可以在MapReduce作用的任意階段啟用。

 二:MapReduce數據壓縮

Map之前的輸入端壓縮 :(Hadoop自動檢查文件擴展名如果擴展名能夠匹配就會使用恰當的編解碼方式對文件進行壓縮和解壓)

Mapper輸出采用壓縮:(可有效改善shuffle過程,此過程是資源消耗最多的環節)

註:(LZO是Hadoop通用的編解碼器,其設計目標是達到與硬盤讀取速度相當的壓縮速度,因此速度是優先考慮的因素,其次是壓縮率,LZO的壓縮速度是Gzip的5倍,解壓速度是Gzip的2倍)

Reducer輸出壓縮:壓縮技術能夠減少要存儲的數據量,將i磁盤空間。

三:壓縮的參數配置

io.compression.codecs   (在core-site.xml中配置)  (map輸入前)

mapreduce.map.output.compress(在mapred-site.xml中配置)  (map到reduce)

mapreduce.map.output.compress.codec(在mapred-site.xml中配置)

mapreduce.output.fileoutputformat.compress(在mapred-site.xml中配置)(reduce輸出)

mapreduce.output.fileoutputformat.compress.codec(在mapred-site.xml中配置)

mapreduce.output.fileoutputformat.compress.type(在mapred-site.xml中配置)

如果壓縮寫到瞭配置文件中則,所有都會進行壓縮,如果隻是寫到瞭當前程序中,隻對當前程序起作用。

3.1:設置reduce輸出端的壓縮格式

//設置Reduced端輸出壓縮
FileOutputFormat.setCompressOutput(job,true);
//壓縮的結果是BZip2Codec
FileOutputFormat.setOutputCompressorClass(job,BZip2Codec.class);
FileOutputFormat.setOutputCompressorClass(job, SnappyCodec.class);

3.2:設置map輸入的壓縮方式

//開啟map輸出壓縮
conf.setBoolean(“mapreduce.map.output.compress”,true);
conf.setClass(“mapreduce.map.output.compress.codec”, BZip2Codec.class, CompressionCodec.class);

四:文件的壓縮與解壓縮案例

public class FileCompress {
    public static void main(String[] args) throws IOException {
        //壓縮傳入兩個參數 path  以及壓縮格式
//        compress("E:\\a.txt","org.apache.hadoop.io.compress.BZip2Codec");
 
        decompress("E:\\a.txt.bz2");
 
    }
 
    private static void decompress(String path) throws IOException {
        //1:校驗是否能解壓    CompressionCodecFactory     A factory that will find the correct codec for a given filename.
        CompressionCodecFactory factory = new CompressionCodecFactory(new Configuration());
        //This class encapsulates a streaming compression/decompression pair.
        CompressionCodec codec = factory.getCodec(new Path(path));
        if (codec == null){
            System.out.println("cannot find codec for file " + path);
            return;
        }
        //2 獲取普通輸入流,再獲取解壓輸入流
        FileInputStream fis = new FileInputStream(new File(path));
        //允許客戶端 重新定義輸入流
        CompressionInputStream cis = codec.createInputStream(fis);
        //3:獲取輸出流
        FileOutputStream fos = new FileOutputStream(new File(path + ".decodec"));
 
        //4 將壓縮輸入流寫入輸出流
        IOUtils.copyBytes(cis , fos, new Configuration());
        //5:關閉資源
        IOUtils.closeStream(fos);
        IOUtils.closeStream(cis);
        IOUtils.closeStream(fis);
 
    }
 
    private static void compress(String path, String method) throws IOException {
        //1:獲取輸入流
        FileInputStream fis = new FileInputStream(path);
        //2:獲取壓縮編碼器   編解碼器就是算嗎
        CompressionCodecFactory factory = new CompressionCodecFactory(new Configuration());
        CompressionCodec codec = factory.getCodecByName(method);
        //3:獲取普通輸出流,獲取壓縮輸出流     獲取編碼器的擴展名
        FileOutputStream fos = new FileOutputStream(new File(path + codec.getDefaultExtension()));
        CompressionOutputStream cos = codec.createOutputStream(fos);
        //4:賦值輸入流到流輸出流
        IOUtils.copyBytes(fis,cos,new Configuration());
        //5 關閉資源
        IOUtils.closeStream(cos);
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);
 
    }
}

到此這篇關於Hadoop中的壓縮的文章就介紹到這瞭,更多相關Hadoop壓縮內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: