首页 > 技术文章 > Hadoop(21)shuffle当中的数据压缩

jimmy888 2020-08-26 23:13 原文

shuffle当中的数据压缩

为什么要压缩?

shuffle阶段,可以看到数据通过大量的拷贝,map阶段输出的数据,都要通过网络拷贝,发送到reduce阶段,这一过程中,涉及到大量的网络IO,如果数据能够进行压缩,那么数据的发送量就会少得多,而且也不会占用那么多本地磁盘空间。

压缩步骤大致处于mapreduce流程中的位置:input--》mapper--》shuffle--》partitioner、sort、combiner、【compress】group--》reducer--》output

那么如何配置hadoop的文件压缩呢,以及hadoop当中的文件压缩支持哪些压缩算法呢??

hadoop当中支持的压缩算法

文件压缩有两大好处,节约磁盘空间,加速数据在网络和磁盘上的传输

我们可以使用bin/hadoop checknative 来查看我们编译之后的hadoop支持的各种压缩,如果出现opensslfalse,那么就在线安装一下依赖包

[hadoop@node01 ~]$ hadoop checknative
20/02/15 13:55:55 INFO bzip2.Bzip2Factory: Successfully loaded & initialized native-bzip2 library system-native
20/02/15 13:55:55 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
Native library checking:
hadoop:  true /kkb/install/hadoop-2.6.0-cdh5.14.2/lib/native/libhadoop.so.1.0.0
zlib:    true /lib64/libz.so.1
snappy:  true /lib64/libsnappy.so.1
lz4:     true revision:10301
bzip2:   true /lib64/libbz2.so.1
openssl: true /lib64/libcrypto.so

可以看到,我们的hadoop经过编译后已经支持所有的压缩格式了,剩下的问题就是我们该如何选择使用这些压缩格式来对我们的MapReduce程序进行压缩。

压缩格式详情如下:

压缩格式 工具 算法 文件扩展名 是否可切分
DEFLATE DEFLATE .deflate
Gzip gzip DEFLATE .gz
bzip2 bzip2 bzip2 bz2
LZO lzop LZO .lzo
LZ4 LZ4 .lz4
Snappy Snappy .snappy

从上图可以看到,上面有些压缩算法是不支持切分的,所以,无论压缩后的压缩文件有没有大于128M,这个压缩文件都只会被当作 一个切片处理。

各种压缩算法对应使用的java类:

压缩格式 对应使用的java类
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

常见的压缩速率比较:

压缩算法 原始文件大小 压缩后的文件大小 压缩速度 解压缩速度
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 135 MB/s 410 MB/s
snappy 8.3GB 1.8GB 172MB/s 409MB/s

常用的压缩算法主要有LZOsnappy

开启压缩的方式

方式一:在main()方法中进行设置
//设置我们的map阶段的压缩
Configuration conf = new Configuration();
conf.set("mapreduce.map.output.compress","true");
conf.set("mapreduce.map.output.compress.codec","org.apache.hadoop.io.compress.SnappyCodec");

//设置我们的reduce阶段的压缩
conf.set("mapreduce.output.fileoutputformat.compress","true");
conf.set("mapreduce.output.fileoutputformat.compress.type","RECORD");
//上面这行代码只有在输出文件的格式是SequenceFile时才会起作用
conf.set("mapreduce.output.fileoutputformat.compress.codec","org.apache.hadoop.io.compress.SnappyCodec");
方式二:修改mapred-site.xml

我们可以修改mapred-site.xml配置文件,然后重启集群,以便对所有的mapreduce任务进行压缩

map输出数据进行压缩:

<property>
	<name>mapreduce.map.output.compress</name>
	<value>true</value>
</property>
<property>
	<name>mapreduce.map.output.compress.codec</name>
	<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property> 

reduce输出数据进行压缩:

<property>    
	<name>mapreduce.output.fileoutputformat.compress</name>
	<value>true</value>
</property>
<property>    
	<name>mapreduce.output.fileoutputformat.compress.type</name>
	<value>RECORD</value>
</property>
<property>    
	<name>mapreduce.output.fileoutputformat.compress.codec</name>
	<value>org.apache.hadoop.io.compress.SnappyCodec</value> 
</property>

所有节点都要修改mapred-site.xml,修改完成之后记得重启集群

案例运行

把分区例子拿到集群运行,并修改mapred-site.xml,使得对reduce的输出进行压缩。运行后的输出文件如下,可以看到,part-r-文件的后缀时.snappy

image-20200215154403743

推荐阅读