文件压缩主要有两方面的好处:一方面节省文件存储空间;另一方面加速网络数据传输或磁盘读写。当处理大规模的数据时这些效果提升更加明显,因此我们需要仔细斟酌压缩在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. QT的信号与槽机制介绍

      信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗 ...

  2. Bigcommerce:intershop编程经验总结

    1.修改或者添加网页Title,Keywords,Decoration的代码: $full_url = $_SERVER['REQUEST_URI'];  //获取请求的url $letter = s ...

  3. Memento 备忘录 快照模式

    简介 定义: 在不破坏封装的前提下,捕获一个对象的[内部状态],并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态. 角色: 发起人Originator:要被备份的成员,它提供一创 ...

  4. noip 2013 华容道

    /*双向bfs (得分和单项的一样多....)70*/ #include<iostream> #include<cstdio> #include<cstring> ...

  5. 【开源java游戏框架libgdx专题】-14-系统控件-Skin类

    Skin类主要用于存储用户界面的资源,该资源主要用于窗口部件.这些资源也包括纹理图片.位图画笔.颜色等内容.方便创建游戏组件,同时使用Skin也可以批量的粗略处理一些窗口部件. test.json { ...

  6. for update被锁定解锁

     查找被锁定的表,用户,session:SELECT object_name, machine, s.sid, s.serial#FROM gv$locked_object l, dba_object ...

  7. 对exp full 和 imp full的认识

    前段时间听同事说.Toad 工具可以打开 oracle数据库的 .dmp 文件.今天抽空试了试,果然可以!Oracle 执行 export 操作 会把 表的定义导出.表的数据导出. 其实 .dmp 文 ...

  8. JavaScript_object(基于map和数组练习)

    JavaScript在编程过程中,不会像java那么方便,提供大量的API让开发这直接去调用,但底层也封装大量的工具让开发者写方法去实现, 以map为例,写简单的增删改查模拟java中的map: fu ...

  9. JAVA-4-斐波列

    public class Ch049 { public static void main(String[] args) { // TODO 自动生成的方法存根 int a = 1, b = 1; fo ...

  10. linux变量心得

    前一段时间学习了一下linux的变量,现在总结有3点需要特别注意: linux变量和C/C++变量的区别 linux变量的引用 linux变量特有的命令替换 先说第一点,linux变量更像是宏定义,只 ...