文件压缩主要有两方面的好处:一方面节省文件存储空间;另一方面加速网络数据传输或磁盘读写。当处理大规模的数据时这些效果提升更加明显,因此我们需要仔细斟酌压缩在Hadoop环境下的使用。
 
目前已经存在很多压缩格式、工具和算法,各有特点,如下图:
 
 
说明:
a. DEFLATE是一种压缩算法,标准实现是zlib,尚没有命令行工具支持。一般情况下使用gzip,相对于DEFLATE而言有额外的头部和尾部。文件扩展名.deflate是一个Hadoop的约定。
 
b. LZO文件经过预处理被索引之后是可以支持切片的。
 
所有的压缩算法都存在空间与时间的权衡:更快的压缩速率和解压速率是以牺牲压缩率为代价的。通常的命令行工具会提供九种不同的权衡选项:-1意味着更快的压缩速率;-9意味着更高的压缩率。如:gzip -1 file意味着使用更快的压缩算法创建压缩文件file.gz。
 
不同的压缩算法拥有不同的压缩特性:
 
gzip是一种常规的压缩工具,空间与时间得到很好的权衡;
 
bzip2压缩率高于gzip,但压缩速度较慢;解析速度优于它的压缩速度,但还是较其它压缩算法偏慢;
 
LZO、LZ4和Snappy相对于gzip而言压缩速度得到很大提升,但没有gzip的压缩率高;而Snappy和LZ4相对于LZO而言在解压速率方面有明显的提升。
 
“Splittable”指示压缩格式是否支持切片,即是否可以在数据流中随意寻址读取数据,可切片的压缩格式非常适合MapRedcue。
 
Codecs
 
Codec是实现特定压缩/解压缩算法的编码解码器。Hadoop Codec必须实现CompressionCodec接口,如下:
 
public interface CompressionCodec {
CompressionOutputStream createOutputStream(OutputStream out) throws IOException;
CompressionOutputStream createOutputStream(OutputStream out, Compressor compressor) throws IOException;
Class<? extends Compressor> getCompressorType();
Compressor createCompressor();
CompressionInputStream createInputStream(InputStream in) throws IOException;
CompressionInputStream createInputStream(InputStream in, Decompressor decompressor) throws IOException;
Class<? extends Decompressor> getDecompressorType();
Decompressor createDecompressor();
String getDefaultExtension();
}
 可用的Codec如下:
 
 
LZO库是基于GPL协议的,没有被包含在Apache的发布版中,需要独立下载。
 
Compressing and decompressing streams with CompressionCodec
 
CompressionCodec有两个方法可以帮助我们方便的压缩或解压数据。压缩数据时使用createOutputStream(OutputStream out)获取压缩输出流,我们将未压缩的数据写入该流,它会帮我们压缩数据后写出至底层的数据流out;相反地,解析数据时使用createInputStream(InputStream in)获取解压缩输入流,通过它我们可以从底层的数据流中读取解压后的数据。
 
CompressionOutputStream、CompressionInputStream与java.util.zip.DeflaterOutputStream、java.util.zip.DeflaterInputStream类似,但是前者支持重置内部的压缩器(Compressor)与解压缩器(Decompressor)状态。如果应用程序需要将数据流中的数据一部分一部分地压缩成“块”的形式,每次压缩完一个“块”之后都需要重置压缩器(Compressor)的状态才可以压缩下一“块”的数据,解压缩时同理。
 
 
这个应用程序读取标准输入流中的数据,使用指定的压缩算法将数据压缩后写出至标准输出流。程序运行时需要提供一个命令行参数:CompressionCodec全限定类名。可以使用下面的命令进行验证:
 
echo "Text" | hadoop StreamCompressor org.apache.hadoop.io.compress.GzipCodec | gunzip
Text
 
Inferring CompressionCodecs using CompressionCodecFactory
 
当我们仅仅需要处理一种特定格式的压缩文件时,我们可以简单的根据这个压缩文件的后缀名决定使用哪个Codec进行数据读取(上述两张图分别给出文件后缀名与压缩格式的对应关系,以及压缩格式与Codec的对应关系);当我们的应用程序需要兼容多种压缩格式时,就需要有一种机制帮助我们根据压缩文件后缀名透明地帮助我们选取合适的Codec。
 
CompressionCodecFactory getCodec()方法可以根据我们提供的一个文件路径(文件名称带有后缀)返回匹配CompressionCodec。
 
CompressionCodecFactory实例初始化时,会在构造方法中维护文件后缀名与CompressionCodec的映射关系,代码如下:
 
 
其中,getCodecClasses返回我们配置(io.compression.codecs)的所有CompressionCodec实例,然后通过addCodec()方法维护映射关系。如果我们没有配置任何需要支持的CompressionCodec,则默认添加GzipCodec,DefaultCodec。
 
 
可以看出文件后缀名是通过CompressionCodec getDefaultExtension()方法获取的,而且经过字符串逆转处理,每一个CompressionCodec实例都会有一个getDefaultExtension()方法,返回此CompressionCodec实例对应的文件后缀名,如GzipCodec:
 
 
addCodec方法很重要的一部分工作就是维护文件后缀名与CompressionCodec之间的映射关系codecs,
 
 
源码注释也强调这里codecs的实现有点“过度”(SortedMap),如果直接使用HashMap表示文件后缀名与CompressionCodec之间的映射关系是不是更简单?
 
 
因为“过度”的使用SortedMap,getCodec的实现也略有点复杂,读者可自行理解,核心思想依然是根据传入的文件路径获取文件后缀名,然后在codecs中寻找匹配的CompressionCodec。
 
CompressionCodecFactory使用示例如下:
 
 
可以看出我们并不需要在程序中显示指定使用哪个CompressionCodec,而是由CompressionCodecFactory帮助我们根据文件后缀名自动推断出相应的CompressionCodec,极大地增强应用程序在处理压缩文件时的通用性。
 
Native libraries
 
Hadoop的压缩库通常会有两种实现,一种是Java实现,另一种是本地库,就性能而言本地库在压缩和解压方面更具优势。比如gzip,使用本地库相比于Java实现,压缩时间可以提高10%,解压缩时间可以提高50%。
 
 
默认情况下,Hadoop会自动在本地库路径(java.library.path)下查询并加载合适的本地库实现,我们可以通过设置属性io.native.lib.available为false禁用本地库,此时内建的Java实现将被使用。
 
CodecPool
 
在应用程序中如果需要使用本地库进行大量的压缩、解压工作,可以考虑通过使用CodecPool重用压缩器(Compressor)和解压缩器(Decompressor),从而避免频繁创建这些对象带来的大量开销。
 
 
 
 
 

Hadoop Compression的更多相关文章

  1. Spark on Yarn出现hadoop.compression.lzo.LzoCodec not found问题发现及解决

    问题描述: spark.SparkContext: Created broadcast 0 from textFile at WordCount.scala:37 Exception in threa ...

  2. [Compression] Hadoop 压缩

    0. 说明 Hadoop 压缩介绍 && 压缩格式总结 && 压缩编解码器测试 1. 介绍 [文件压缩的好处] 文件压缩的好处如下: 减少存储文件所需要的磁盘空间 加速 ...

  3. hadoop安装遇到的各种异常及解决办法

    hadoop安装遇到的各种异常及解决办法 异常一: 2014-03-13 11:10:23,665 INFO org.apache.hadoop.ipc.Client: Retrying connec ...

  4. Hadoop安装lzo实验

    参考http://blog.csdn.net/lalaguozhe/article/details/10912527 环境:hadoop2.3cdh5.0.2 hive 1.2.1 目标:安装lzo ...

  5. hadoop core-site.xml

    <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text ...

  6. Hadoop配置文件

    部分内容参考:http://www.linuxqq.net/archives/964.html  http://slaytanic.blog.51cto.com/2057708/1100974/ ht ...

  7. Hadoop使用lzo压缩格式

    在hadoop中搭建lzo环境: wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.06.tar.gz export CFLAGS ...

  8. 使用yum安装CDH Hadoop集群

    使用yum安装CDH Hadoop集群 2013.04.06 Update: 2014.07.21 添加 lzo 的安装 2014.05.20 修改cdh4为cdh5进行安装. 2014.10.22  ...

  9. [大牛翻译系列]Hadoop(20)附录A.10 压缩格式LZOP编译安装配置

    附录A.10 LZOP LZOP是一种压缩解码器,在MapReduce中可以支持可分块的压缩.第5章中有一节介绍了如何应用LZOP.在这一节中,将介绍如何编译LZOP,在集群做相应配置. A.10.1 ...

随机推荐

  1. <<java 并发编程>>第七章:取消和关闭

    Java没有提供任何机制来安全地终止线程,虽然Thread.stop和suspend等方法提供了这样的机制,但是存在严重的缺陷,应该避免使用这些方法.但是Java提供了中断Interruption机制 ...

  2. [转] Form表单中method="post/get'的区别

    Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的影响.虽然为了方便的得到变量值,Web容器已经屏蔽了二者的一 ...

  3. Android短信的发送和接收监听

    /**发送与接收的广播**/ String SENT_SMS_ACTION = "SENT_SMS_ACTION"; String DELIVERED_SMS_ACTION = & ...

  4. Android实现网络多线程断点续传下载(转)

    本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...

  5. android中的数据库操作(转)

    android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库   an ...

  6. ListView滑动删除

    本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示.但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制.所以决定继承List ...

  7. codevs2034 01串2

    /* 一开始认为是个水题 直接模拟 没想到只得了50分 一看数据吓niao了 模拟妥妥的TLE 实在不好优化了0.0(最快O(m)) 然后借鉴别人的 DP+神奇的输出 DP:状态:f[i][j] 前i ...

  8. Rational rose下载,安装,破解

    rationalrose是一个镜像文件,后缀名是bin 之前尝试过用虚拟光驱来打开,不知道为什么,在win10的环境下,虚拟光驱硬是不能加载bin文件,后来拷到虚拟机上,打开了bin镜像文件,得到了一 ...

  9. HDU5319

    题意:给一个矩形染色,顺笔表示红色,逆笔表示蓝色(既一捺和一丿),交叉表示绿色,然后给你一个图,问你用多少笔能画出这个图来. 思路:对这个图直接模拟即可,如果点i,j坐标为红色,那么判断上一个路径点是 ...

  10. 网页嵌入百度地图和使用百度地图api自定义地图的详细步骤

    在网页中插入百度地图 如果想在自己的网页上面加入百度地图的话,可以用百度地图的api.具体使用方法如下: 第一步:进入百度创建地图的网站http://api.map.baidu.com/lbsapi/ ...