一、概述

压缩技术能够有效减少底层存储系统(HDFS)读写字节数。压缩提高了网络带宽和磁盘空间的效率。在运行MR程序时,I/O操作、网络数据传输、 Shuffle 和Merge要花大量的时间,尤其是数据规模很大和工作负载密集的情况下,因此, 使用数据压缩显得非常重要。
鉴于磁盘I/O和网络带宽是Hadoop的宝贵资源,数据压缩对于节省资源、最小化磁盘I/O和网络传输非常有帮助。可以在任意MapReduce阶段启用压缩。不过,尽管压缩与解压操作的CPU开销不高,其性能的提升和资源的节省并非没有代价。

压缩策略和原则

压缩是提高Hadoop运行效率的一种优化策略。 通过对Mapper、Reducer运行过程的数据进行压缩,以减少磁盘IO, 提高MR程序运行速度。
注意:采用压缩技术减少了磁盘IO,但同时增加了CPU运算负担。所以,压缩特性运用得当能提高性能,但运用不当也可能降低性能。

  1. <br />压缩基本原则:
  • 运算密集型的job,少用压缩

  • IO密集型的job,多用压缩

二、压缩编码

MR支持的压缩编码

image.pngimage.png

编码/解码器

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

压缩性能比较

image.png
Snappy:http://google.github.io/snappy/
On a single core of a Core i7 processor in 64-bit mode, Snappy compresses at about 250 MB/sec or more and decompresses at about 500 MB/sec or more

三、压缩方式的选择

gzip压缩

优点:压缩率比较高,而且压缩/解压速度也比较快;Hadoop本身支持,在 应用中处理Gzip格式的文件就和直接处理文本一样;大部分Linux系统都自带 Gzip命令,使用方便。
缺点:不支持Split。
应用场景:当每个文件压缩之后在130M以内的(1个块大小内),都可以考虑用Gzip压缩格式。例如说一天或者一个小时的日志压缩成一个Gzip文件。

Bzip2压缩

优点:支持Split;具有很高的压缩率,比Gzip压缩率都高;Hadoop本身自 带,使用方便。
缺点:压缩/解压速度慢。
应用场景:适合对速度要求不高,但需要较高的压缩率的时候;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持Split,而且兼容之前的应用程序的情况

Lzo压缩

优点:压缩/解压速度也比较快,合理的压缩率;支持Split,是Hadoop中最流行的压缩格式;可以在Linux系统下安装lzop命令,使用方便。
缺点:压缩率比Gzip要低一些;Hadoop本身不支持,需要安装;在应用中对Lzo格式的文件需要做一些特殊处理(为了支持Split需要建索引,还需要指 定InputFormat为Lzo格式)。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑, 而且单个文件越大,Lzo优点越越明显。

Snappy压缩

优点:高速压缩速度和合理的压缩率。
缺点:不支持Split;压缩率比Gzip要低;Hadoop本身不支持,需要安装。
应用场景:当MapReduce作业的Map输出的数据比较大的时候,作为Map到 Reduce的中间数据的压缩格式;或者作为一个MapReduce作业的输出和另外一 个MapReduce作业的输入

四、压缩位置选择

压缩可以在MapReduce作用的任意阶段使用:
image.png

五、压缩参数配置

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

参数 默认值 阶段 建议



io.compression.codecs

(在 core-site.xml 中配置) | org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec |


输入压缩 |


Hadoo p使用 文件扩 展名判断是否支持某种编解 码器 | |


mapreduce.map.output.co mpress ( 在 mapred- site.xml 中配置)

  1. | <br /><br /><br /><br />false


  1. | <br /><br /><br /><br />mapper 输出


  1. | <br /><br /><br /><br />这个参

数设为 true 启 用压缩

  1. |

|


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

  1. | <br /><br /><br /><br />org.apache.hadoop.io.compress.DefaultCodec


  1. | <br /><br /><br /><br />mapper 输出


  1. | <br /><br /><br /><br />企业多使用

LZO 或 Snappy 编解码器在此阶段压缩数据

  1. |

|


mapreduce.output.fileoutp utformat.compress ( 在 mapred-site.xml 中配置)

  1. | <br /><br /><br /><br />false


  1. | <br /><br /><br /><br />reducer 输出


  1. | <br /><br /><br /><br />这个参

数设为 true 启用压缩

  1. |

|


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

  1. | <br /><br /><br /><br />org.apache.hadoop.io.compress.

DefaultCodec

  1. | <br /><br /><br /><br />reducer 输出


  1. | <br /><br /><br /><br />使用标准工具

或者编解码器,如 gzip 和 bzip2

  1. |

|


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

  1. | <br /><br /><br /><br />RECORD


  1. | <br /><br /><br /><br />reducer 输出


  1. | <br /><br /><br /><br />SequenceFile

输出使用的压缩类 型: NONE 和 BLOCK

  1. |

六、压缩实例

6.1、数据流的压缩和解压缩

CompressionCodec有两个方法可以用于轻松地压缩或解压缩数据。
要想对正在被写入一个输出流的数据进行压缩,我们可以使用 createOutputStream(OutputStreamout) 方法创建 一个 CompressionOutputStream , 将其以压缩格式写入底层的流。
相反,要想对从输入流读取而来的数据进行解压缩,则调用 createInputStream(InputStreamin)函数,从而获得一个CompressionInputStream,从而从底层的流读取未压缩的数据。
案例:https://github.com/Wells-Lee/mapreduce-demo/tree/master/src/main/java/com/wells/demo/compress/demo

6.2、Mapper输出端压缩

即使你的 MapReduce 的输入输出文件都是未压缩的文件,你仍然可以对 Map 任务的中 间结果输出做压缩,因为它要写在硬盘并且通过网络传输到 Reduce 节点,对其压缩可以提 高很多性能,这些工作只要设置两个属性即可。
在Driver的配置中设置,其他:Mapper、Reducer不用变

  1. // 开启 map 端输出压缩
  2. configuration.setBoolean("mapreduce.map.output.compress", true);
  3. // 设置 map 端输出压缩方式
  4. configuration.setClass("mapreduce.map.output.compress.codec" , BZip2Codec.class, CompressionCodec.class);

6.3、Reduce输出端压缩

在Driver的配置中设置,其他:Mapper、Reducer不用变

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