Hadoop3教程(二十一):MapReduce中的压缩-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

123压缩概述

压缩也是MR中比较重要的一环其可以应用于Map阶段比如说Map端输出的文件也可以应用于Reduce阶段如最终落地的文件。

压缩的好处是减少磁盘的IO以及存储空间。缺点也很明显就是极大增加了CPU的开销频繁计算带来的频繁压缩与解压缩。

压缩的基本原则

  • 对运算密集型job少用压缩计算时需要解压缩计算完需要压缩受不了
  • 对IO密集型Job多用压缩。

MR支持很多种压缩算法常用的有以下几个

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

支持切片的话使用上会更方便很多。

压缩性能的比较如下

压缩算法原始文件大小压缩文件大小压缩速度解压速度
gzip8.3GB1.8GB17.5MB/s58MB/s
bzip28.3GB1.1GB2.4MB/s9.5MB/s
LZO8.3GB2.9GB49.3MB/s74.6MB/s

据说最好的还是Google开发的snappy其官网介绍它的压缩速度是250MB/s解压缩速度是500MB/s。

那在生产环境下该如何选择合适的压缩方式呢

一般是重点考虑以下几点

  • 压缩/解压缩速度
  • 压缩率即压缩后的文件大小
  • 压缩后是否还支持切片。

结合这几点我们再回头看这几种压缩算法。

Gzip压缩压缩率比较高但是压缩/解压缩速度一般且不支持切片

Bzip2压缩压缩率非常高且支持切片但是压缩/解压缩速度极慢

Lzo压缩压缩/解压缩速度非常快且支持切片但是压缩率一般不过Lzo需要额外创建索引之后才能支持切片。

Snappy压缩压缩和解压缩速度极快但不支持切片压缩率一般。

压缩可以在MapReduce的任意阶段启用一共三个阶段即Map的输入端、Map到Reduce部分、Reduce的输出端。

在Map阶段启用

在Map的输入端启用压缩时

不需要显式指定使用的编解码方式Hadoop会自动通过文件扩展名来选择合适的编解码方式。

同时需要注意如果数据量小于块大小的话则可以考虑压缩、解压缩速度比较快的算法如LZO、snappy如果数据量大于块大小的话则可以重点考虑支持切片的算法如Bzip2和LZO。

在Mapper的输出端启用压缩时

这里启用压缩主要是为了减少MapTask和ReduceTask之间的网络IO所以可以选择重点考虑压缩和解压缩快的LZO、snappy等。

在Reduce阶段启用

在Reducer的输出端启用压缩时

如果输出的数据是需要永久保存那么可以采用压缩率比较高的算法以减少存储的空间

如果是作为下一个MapReduce的输入那么可以考虑数据量和是否支持切片。

124压缩案例实操

讲怎么写压缩代码的此处只做了解所以基本是直接复制教程文档。

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

压缩格式对应的编码/解码器
DEFLATEorg.apache.hadoop.io.compress.DefaultCodec
gziporg.apache.hadoop.io.compress.GzipCodec
bzip2org.apache.hadoop.io.compress.BZip2Codec
LZOcom.hadoop.compression.lzo.LzopCodec
Snappyorg.apache.hadoop.io.compress.SnappyCodec

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

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

抄一下案例。

如何在Map输出端启用压缩

假如想Mapper输出端启用压缩只需要调整驱动类即可Mapper和Reducer类不需要做特殊处理跟正常一样就可以。

package com.atguigu.mapreduce.compress;
import java.io.IOException;
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.GzipCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCountDriver {

	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

		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);

		job.setJarByClass(WordCountDriver.class);

		job.setMapperClass(WordCountMapper.class);
		job.setReducerClass(WordCountReducer.class);

		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);

		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);

		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));

		boolean result = job.waitForCompletion(true);

		System.exit(result ? 0 : 1);
	}
}

如何在Reduce端启用压缩

假如想Reducer输出端启用压缩

package com.atguigu.mapreduce.compress;
import java.io.IOException;
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.DefaultCodec;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.io.compress.Lz4Codec;
import org.apache.hadoop.io.compress.SnappyCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCountDriver {

	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		
		Configuration conf = new Configuration();
		
		Job job = Job.getInstance(conf);
		
		job.setJarByClass(WordCountDriver.class);
		
		job.setMapperClass(WordCountMapper.class);
		job.setReducerClass(WordCountReducer.class);
		
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		
		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); 
	    
		boolean result = job.waitForCompletion(true);
		
		System.exit(result?0:1);
	}
}

参考文献

  1. 【尚硅谷大数据Hadoop教程hadoop3.x搭建到集群调优百万播放】
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Hadoop