Hadoop中的压缩(1) 概述与实例

1 概述

文件压缩主要有两个好处,一是减少了存储文件所占空间,另一个就是为数据传输提速。在hadoop大数据的背景下这两点尤为重要。hadoop里支持很多种压缩格式:

DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法,源代码可以在zlib库中找到。gzip是以DEFLATE算法为基础扩展出来的一种算法。


压缩算法


原始文件大小


压缩后的文件大小


压缩速度


解压缩速度


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


49.3MB/S


74.6MB/s

 

 

 

所有的压缩算法都是空间和时间的转换,更快压缩时间还是更小的压缩比,可以通过参数来指定,-1意味着速度,-9意味着空间。拿gzip做个例子,下面就意味着更快速的压缩:gzip -1 file

gzip在时间和空间上的取舍比较折中,bzip2压缩比gzip更有效,但是速度更慢。bzip2的解压速度比它的压缩速度要快。但是和其他压缩格式比又是最慢的,但是压缩效果明显是最好的。snappy和lz4的解压速度比lzo好很多。splittable表示压缩格式是否可以被分割,也就是说是否支持随即读。压缩数据是否能被mapreduce使用,压缩数据是否能被分割就很关键了。

举例一个未压缩的文件有1GB大小,hdfs默认的block大小是64MB,那么这个文件就会被分为16个block作为mapreduce的输入,每一个单独使用一个map任务。若该文件是已经使用gzip压缩的呢,若分成16个块,每个块做成一个输入,显然是不合适的,因为gzip压缩流的随即读是不可能的。实际上,当mapreduce处理压缩格式的文件的时候它会认识到这是一个gzip的压缩文件,而gzip又不支持随即读,它就会把16个块分给一个map去处理,这里就会有很多非本地处理的map任务,整个过程耗费的时间就会相当长。lzo压缩格式也会是同样的问题,但是通过使用hadoop
lzo库的索引工具以后,lzo就可以支持splittable。bzip2也是支持splittable的。

详见hadoop-2.5.2-src源码中的FileInputFormat类中的getSplits方法

        if (isSplitable(fs, path)) {
          long blockSize = file.getBlockSize();
          long splitSize = computeSplitSize(goalSize, minSize, blockSize);

          long bytesRemaining = length;
          while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
            String[] splitHosts = getSplitHosts(blkLocations,
                length-bytesRemaining, splitSize, clusterMap);
            splits.add(makeSplit(path, length-bytesRemaining, splitSize,
                splitHosts));
            bytesRemaining -= splitSize;
          }

          if (bytesRemaining != 0) {
            String[] splitHosts = getSplitHosts(blkLocations, length
                - bytesRemaining, bytesRemaining, clusterMap);
            splits.add(makeSplit(path, length - bytesRemaining, bytesRemaining,
                splitHosts));
          }
        } else {
          String[] splitHosts = getSplitHosts(blkLocations,0,length,clusterMap);
          splits.add(makeSplit(path, 0, length, splitHosts));
        }

那么如何选择压缩格式呢?这取决于文件的大小,你使用的压缩工具,下面是几条选择建议,效率由高到低排序:
1用一些包含了压缩并且支持splittable的文件格式,比如Sequence File,RCFile或者Avro文件,这些文件格式我们之后都会讲到。若为了快速压缩可以使用lzo,lz4或者snappy压缩格式。
2 使用提供splittable的压缩格式,比如,bzip2和索引后可以支持splittable的lzo。
3 提前把文件分成几个块,每个块单独压缩,这样就无需考虑splittable的问题了
4 不要压缩文件。以不支持splittable的压缩格式存储一个很大的数据文件是不合适的,非本地处理效率会非常之低。

2 代码

codec其实就是coder和decoder两个单词的词头组成的缩略词。CompressionCodec定义了压缩和解压接口,所以又叫编码解码器。为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示


压缩格式


对应的编码/解码器


DEFLATE


org.apache.hadoop.io.compress.DefaultCodec


gzip


org.apache.hadoop.io.compress.GzipCodec


bzip


org.apache.hadoop.io.compress.Bzip2Codec


Snappy


org.apache.hadoop.io.compress.SnappyCodec

public class TestCompress {
	public static void main(String[] args) throws IOException,
			InterruptedException, ClassNotFoundException {
		// 将a.txt压缩为a.txt.bz2
		compress("E://a.txt", "BZip2Codec");
		// 将a.txt.bz2解压为a.txt.bz2.decoded
		decompres("E://a.txt.bz2");
		System.out.println("down");
	}

	/**
	 * 压缩方法
	 * @param filename 待压缩的文件路径
	 * @param method 压缩方法名
	 */
	public static void compress(String filePath, String method)
			throws ClassNotFoundException, IOException {

		// 需要被压缩的文件
		File fileIn = new File(filePath);
		InputStream in = new FileInputStream(fileIn);

		// 通过名称反射得到编码解码器
		Configuration conf = new Configuration();
		Class<?> codecClass = Class.forName("org.apache.hadoop.io.compress."
				+ method);
		CompressionCodec codec = (CompressionCodec) ReflectionUtils
				.newInstance(codecClass, conf);
		// 获取文件扩展名并创建结果文件名
		File fileOut = new File(filePath + codec.getDefaultExtension());
		OutputStream out = new FileOutputStream(fileOut);
		// 输出到结果文件,缓冲区设为5MB
		CompressionOutputStream cout = codec.createOutputStream(out);
		IOUtils.copyBytes(in, cout, 1024 * 1024 * 5, false);
		System.out.println("compress success");
		in.close();
		cout.close();
	}

	/**
	 * 解压方法
	 * @param filename 待解压的文件
	 */
	public static void decompres(String filePath) throws FileNotFoundException,
			IOException {
		// 根据文件后缀获取解码器
		Configuration conf = new Configuration();
		CompressionCodecFactory factory = new CompressionCodecFactory(conf);
		CompressionCodec codec = factory.getCodec(new Path(filePath));
		if (null == codec) {
			System.out.println("Cannot find codec for file " + filePath);
			return;
		}
		// 获取输入流
		InputStream cin = codec
				.createInputStream(new FileInputStream(filePath));
		// 输出文件
		File fout = new File(filePath + ".decoded");
		OutputStream out = new FileOutputStream(fout);
		IOUtils.copyBytes(cin, out, 1024 * 1024 * 5, false);
		System.out.println("decompres success");
		cin.close();
		out.close();
	}
}

原贴地址:http://blog.csdn.net/lastsweetop/article/details/9162031

时间: 2024-11-05 12:22:57

Hadoop中的压缩(1) 概述与实例的相关文章

hadoop中使用lzo的压缩

在hadoop中使用lzo的压缩算法可以减小数据的大小和数据的磁盘读写时间,不仅如此,lzo是基于block分块的,这样他就允许数据被分解成chunk,并行的被hadoop处理.这样的特点,就可以让lzo在hadoop上成为一种非常好用的压缩格式. lzo本身不是splitable的,所以当数据为text格式时,用lzo压缩出来的数据当做job的输入是一个文件作为一个map.但是 sequencefile本身是分块的,所以sequencefile格式的文件,再配上lzo的压缩格式,就可实现lzo

4种常用压缩格式在Hadoop中的应用

目前在Hadoop中用得比较多的有lzo,gzip,snappy,bzip2这4种压缩格式,笔者根据实践经验介绍一下这4种压缩格式的优缺点和应用场景,以便大家在实践中根据实际情况选择不同的压缩格式. 1 gzip压缩 优点:压缩率比较高,而且压缩/解压速度也比较快;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;有hadoop native库;大部分linux系统都自带gzip命令,使用方便. 缺点:不支持split. 应用场景:当每个文件压缩之后在130M以内的(1个

建立HBase的集群和HDInsight在Hadoop中使用Hive来查询它们

建立HBase的集群和HDInsight在Hadoop中使用Hive来查询它们 在本教程中,您将学习如何创建和查询HDInsight使用HiveHadoop的HBase的表.下列步骤描述:•如何使用提供在Azure门户的HBase的集群.•如何启用和使用RDP访问HBase的外壳,并使用HBase的外壳创建HBase的示例表,添加行,然后列出表中的行.•如何创建一个Hive表映射到一个现有的HBase的表,使用HiveQL查询数据在HBase的表.•如何使用Microsoft HBase的RES

hadoop中实现定制Writable类

Hadoop中有一套Writable实现可以满足大部分需求,但是在有些情况下,我们需要根据自己的需要构造一个新的实现,有了定制的Writable,我们就可以完全控制二进制表示和排序顺序. 为了演示如何新建一个定制的writable类型,我们需要写一个表示一对字符串的实现: blic class TextPair implements WritableComparable<TextPair> { private Text first; private Text second; public Te

Hadoop中的Context使用

Hadoop中的Context使用.简要截取: 本文以经典的wordcount程序为例来说明context的用法: 直接上代码: package MapReduce; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import

Hadoop中Partition深度解析

旧版 API 的 Partitioner 解析 Partitioner 的作用是对 Mapper 产生的中间结果进行分片,以便将同一分组的数据交给同一个 Reducer 处理,它直接影响 Reduce 阶段的负载均衡.旧版 API 中 Partitioner 的类图如图所示.它继承了JobConfigurable,可通过 configure 方法初始化.它本身只包含一个待实现的方法 getPartition. 该方法包含三个参数, 均由框架自动传入,前面两个参数是key/value,第三个参数

hadoop中InputFormat 接口的设计与实现

InputFormat 主要用于描述输入数据的格式, 它提供以下两个功能. 数据切分:按照某个策略将输入数据切分成若干个 split, 以便确定 Map Task 个数以及对应的 split. 为 Mapper 提供输入数据: 给定某个 split, 能将其解析成一个个 key/value 对. 本文将介绍 Hadoop 如何设计 InputFormat 接口,以及提供了哪些常用的 InputFormat实现. 1 .旧版 API 的 InputFormat 解析 如图所示: 在旧版 API 中

hadoop中的序列化与Writable接口

简介 序列化和反序列化就是结构化对象和字节流之间的转换,主要用在内部进程的通讯和持久化存储方面. 通讯格式需求 hadoop在节点间的内部通讯使用的是RPC,RPC协议把消息翻译成二进制字节流发送到远程节点,远程节点再通过反序列化把二进制流转成原始的信息.RPC的序列化需要实现以下几点: 1.压缩,可以起到压缩的效果,占用的宽带资源要小. 2.快速,内部进程为分布式系统构建了高速链路,因此在序列化和反序列化间必须是快速的,不能让传输速度成为瓶颈. 3.可扩展的,新的服务端为新的客户端增加了一个参

hadoop中slot简介(map slot 和 reduce slot)

Slots是Hadoop的一个重要概念.然而在Hadoop相关论文,slots的阐述难以理解.网上关于slots的概念介绍也很少,而对于一个有经验的Hadoop开发者来说,他们可能脑子里已经理解了slots的真正含义,但却难以清楚地表达出来,Hadoop初学者听了还是云里雾里.我来尝试讲解一下,以期抛砖引玉. 首先,slot不是CPU的Core,也不是memory chip,它是一个逻辑概念,一个节点的slot的数量用来表示某个节点的资源的容量或者说是能力的大小,因而slot是 Hadoop的资