5.4 压缩

来源:互联网 发布:软件项目验收方案 编辑:程序博客网 时间:2024/05/21 10:14

5.4 压缩

  为了节省存储空间和网络数据传输量,我们会反复提到压缩这个问题。当处理大量数据时,只要有办法减少存储空间和网络数据传输量,就能在速度和成本两方面给予效率提升。压缩就是这样一种策略,能帮助基于Hadoop更高效。

  所有的压缩技术都在压缩速度和压缩效率之间进行了折衷。压缩率越高,压缩速度越慢,反之亦然。每种压缩技术都可以通过调整来权衡以上两个方面。例如,gzip压缩工具提供了选项-1到-9,-1优化压缩速度,-9优化压缩率。

  下图显示了不同压缩算法在速度-空间这两项上的不同表现。gzip算法较好的平衡了存储和速度。其他算法,如LZO,LZ4,Snappy,虽然压缩速度很快,但它们的压缩率不高。Bzip2算法压缩速度较慢,但压缩率最高。

  编解码器是压缩技术的具体实现。Hadoop中所有的压缩编解码器都需在它们的实现类中实现CompressionCodec接口。编解码器位于org.apache.hadoop.io.compress包中。那里有个Hadoop自带的默认编解码器,其压缩算法基于DEFLATE算法。DEFLATE算法类似于gzip,但不包含额外的头部和尾部信息。

5.4.1 分片于压缩

  Map任务处理数据的单个分片,分片通常是保存在HDFS中的一个文件块。但是,大多数压缩算法并不允许在任意位置读取文件。尽管有些压缩算法(如gzip)是基于块的压缩技术,但这里所说的块与HDFS中的块没有关系,或者说HDFS的块对算法透明。在这种情况下,Hadoop不会切分文件,而是把整个文件交给单个Map任务处理。在多数情况下,这种处理方式是不恰当的。

  某些压缩算法,如LZO,提供了索引工具,这个工具可以处理LZO文件并构建压缩块的索引。那么,对应的InputFormat方法就可以使用这些索引,来确定分片数量和分片的偏移量。例如,LzoTextInputFormat可以读取基于LZO文件的索引,从而确定Map任务的输入分片。

  然而,有些压缩技术(如bzip2)天生就可以切分,它们利用同步标记来标识切分点。Hadoop通过文件的扩展名来识别不同的压缩格式。

  启用压缩后,有以下一些策略可供选择。

  • 应用程序可以在预处理阶段切分文件,然后使用流行的压缩技术(如gzip)对文件分片进行压缩。这些压缩文件块保存在HDFS中。压缩后的文件块大小要几乎等于HDFS块大小,这样才算最优。这种情况下,不用担心压缩算法是否可切分。
  • 对文件可直接应用可切分的压缩算法,如bzip2。但是,在支持的压缩编解码器中,bzip2压缩速度最慢。可以用LZO来代替,然后在LZO文件上构建索引。
  • 有些文件格式,如SequenceFile,MapFile,RCFile,天生就支持切分。它们也可被压缩。
  • 把数据保存在专门的文件格式中,这是行业首选的实践方法。这样可以获得速度与压缩之间的平衡。

5.4.2 压缩范围

  通过对MapReduce数据流中的很多地方采用压缩技术,可以提高作业处理速度并降低存储消耗。本小节总结:

  • Map任务中会处理和解压缩所有压缩后的输入数据,根据文件的扩展名来确定压缩编解码器。某些情况下,比如使用带有索引的LZO压缩,需要使用特定的InputFormat类来处理特定的分片。
  • 配置mapreduce.map.output.compress属性为true可启用对中间输出结果的压缩功能。配置mapreduce.map.output.compress.codec属性可设置所用的压缩编解码器,其默认值是org.apache.hadoop.compress.DefaultCodec。
  • 配置mapreduce.output.fileoutputformat.compress.codec属性为true可启用对作业输出结果的压缩功能。配置mapreduce.output.fileoutputformat.compress.codec属性可设置所用的编解码器。如果输出结果是SequenceFile,有个特别的mapreduce.output.fileoutputformat.compress.type属性,用于确定压缩粒度。默认值是RECORD,代表每条记录被单独压缩。设置为BLOCK可压缩成组记录。