Hadoop 数据压缩

1.概述

1.好处 & 坏处

优点:减少磁盘IO、减少磁盘存储空间
缺点:增加CPU开销

2.压缩的原则

  1. 运算密集型的Job,少用压缩
  2. IO密集型的Job,多用压缩

2.MR 支持的压缩编码

1.压缩算法对比介绍

压缩格式 Hadoop自带? 算法 文件扩展名 是否可切片 换成压缩格式后,原来的程序是否需要修改
DEFLATE 是,直接使用 DEFLATE .deflate 和文本处理一样,不需要修改
Gzip 是,直接使用 DEFLATE .gz 和文本处理一样,不需要修改
bzip2 是,直接使用 bzip2 .bz2 和文本处理一样,不需要修改
LZ0 否,需要安装 LZ0 .lzo 需要建索引,还需要指定输入格式
Snappy 是,直接使用(3.x) Snappy .snappy 和文本处理一样,不需要修改

2.压缩性能的比较

压缩算法 原始文件大小 压缩文件大小 压缩速度 解压速度
gzip 8.3GB 1.8GB 17.5MB/S 58MB/S
bzip2 8.3GB 1.1GB 2.4MB/S 9.5MB/S
LZO 8.3GB 2.9GB 49.3MB/S 74.6MB/S

3.压缩方式选择

压缩方式选择时重点考虑:压缩/解压缩速度、压缩率(压缩后存储大小)、压缩后是否可以支持切片

1.Gzip压缩

  • 优点:压缩率比较高
  • 缺点:不支持切片,压缩/解压缩速度一般

2.Bzip2压缩

  • 优点:压缩率高,支持切片
  • 缺点:压缩/解压缩速度慢

3.Lzo压缩

  • 优点:压缩/解压缩速度比较快,支持切片
  • 缺点:压缩率一般,想支持切片需要额外创建索引

4.Snappy压缩

  • 优点:压缩/解压缩速度快
  • 缺点:不支持切片,压缩率一般

5.压缩位置选择

压缩可以在MapReduce作用的任意阶段启用。

  1. Mapper输入前采用压缩
    无需显示指定使用的编解码方式。Hadoop自动检查文件扩展名,如果扩展名能够匹配,就会用恰当的编解码方式对文件进行压缩和解压。
    企业开发:考虑因素
    1. 数据量小于块大小,重点考虑压缩和解压缩速度比较快的LZO/Snappy
    2. 数据量非常大,重点考虑支持切片的Bzip2和LZO
  2. Mapper输出采用压缩
    为了减少MapTask和ReduceTask之间的网络IO,重点考虑压缩和解压缩快的LZO/Snappy
  3. Ruducer输出采用压缩
    看需求:
    • 如果数据永久保存,考虑压缩率比较高的Bzip2和Gzip。
    • 如果作为下一个MapReduce输入,需要考虑数据量和是否支持切片。

4.压缩参数配置

1.编码/解码器

为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器

压缩格式 对应的编码/解码器
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
Snappy org.apache.hadoop.io.compress.SnappyCodec

2.启用压缩配置

要在Hadoop中启用压缩,可以配置如下参数

参数 默认值 阶段 建议
io.compression.codecs(在core-site.xml中配置) 无,这个需要在命令行输出 hadoop checknative查看 输入压缩 Hadoop使用文件扩展名判断是否支持某种编解码器
mapreduce.map.output.compress(在mapred-site.xml中配置) false mapper输出 这个参数设为true启用压缩
mapreduce.map.output.compress.codec(在mapred-site.xml中配置) org.apache.hadoop.io.compress.DefaultCodec mapper输出 企业多使用LZO或Snappy编解码器在此阶段压缩数据
mapreduce.output.fileoutputformat.compress(在mapred-site.xml中配置) false reducer输出 这个参数设为true启用压缩
mapreduce.output.fileoutputformat.compress.codec(在mapred-site.xml中配置) org.apache.hadoop.io.compress.DefaultCodec reducer输出 使用标准工具或者编解码器,如gzip和bzip2

5.案例

package cn.coreqi.mapreduce.wordcount;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.DefaultCodec;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordCountDriver {

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        // 1.获取job
        Configuration conf = new Configuration();
        // 开启map端输出压缩
        conf.setBoolean("mapreduce.map.output.compress",true);
        // 设置map端输出压缩方式
        conf.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class, CompressionCodec.class);

        Job job = Job.getInstance(conf);

        // 2.设置jar包路径
        job.setJarByClass(WordCountDriver.class);   //通过反射指定类所在的包地址来获取当前jar包的路径

        // 3.关联mapper和reducer
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        // 4.设置mapper输出的KV类型[因为泛型擦除的问题,所以需要手动指定类型]
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        // 5. 设置最终输出(reducer)的KV类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        job.setCombinerClass(WordCountCombiner.class);


        // 6. 设置输入路径和输出路径(本地模式)
//        FileInputFormat.setInputPaths(job,new Path("D:\\intput\\inputword"));
//        FileOutputFormat.setOutputPath(job,new Path("D:\\hadoop\\output"));

        // 6. 设置输入路径和输出路径(读取命令行参数集群模式运行)
        FileInputFormat.setInputPaths(job,new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));

        // 设置 reduce端输出压缩开启
        FileOutputFormat.setCompressOutput(job,true);
        
        // 设置压缩的方式
        FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
        //FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
        //FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);

        // 7.提交job,获取更多返回信息
        boolean result = job.waitForCompletion(true);

        System.exit(result ? 0 : 1);
    }
}
posted @ 2023-12-16 18:48  SpringCore  阅读(12)  评论(0编辑  收藏  举报