[大牛翻译系列]Hadoop(19)MapReduce 文件处理:基于压缩的高效存储(二)
5.2 基于压缩的高效存储(续)
(仅包括技术27)
技术27 在MapReduce,Hive和Pig中使用可分块的LZOP
如果一个文本文件即使经过压缩后仍然比HDFS的块的大小要大,就需要考虑选择一个支持分块的压缩编码器,以防一个单一的map任务来处理整个超大的文件。
LZOP可以满足分块的要求,但是使用起来很复杂。原因在于LZOP不是直接支持分块。LZOP是基于块的格式,但是并不支持块的随机访问。
问题
需要选择一个压缩编码器使MapReduce可以调用多个任务并行处理一个单一的压缩文件。
方案
在MapReduce中,对LZOP压缩的输入文件进行分块需要使用针对LZOP的输入格式类,如LzoInputFormat。在Pig和Hive中使用LZOP也是如此。
讨论
压缩编码器中只有LZOP和bzip2支持分块。Bzip2压缩太慢,以至于不太可靠。LZOP在压缩率和速度之间取得了相对可靠的平衡。
在集群配置LZOP
不幸的是,由于授权原因,Hadoop并没有自带LZOP。要在集群中将一切准备工作做好将非常费劲。附录A.10中有配置LZOP的具体步骤。(译注:附录A.10的翻译见下一篇翻译文章。http://www.cnblogs.com/datacloud/p/3617586.html)
在HDFS中读写LZOP文件
在此前的技术中(技术25, 26)介绍了如何读取并写入压缩文件。读写LZOP需要在代码中指定LZOP编码器。实现代码如下所示:
Methods to read and write LZOP files in HDFS
public static Path compress(Path src, Configuration config)
throws IOException { Path destFile = new Path(src.toString() + new LzopCodec().getDefaultExtension());
LzopCodec codec = new LzopCodec();
codec.setConf(config);
FileSystem hdfs = FileSystem.get(config);
InputStream is = null; OutputStream os = null; try {
is = hdfs.open(src);
os = codec.createOutputStream(hdfs.create(destFile));
IOUtils.copyBytes(is, os, config);
} finally {
IOUtils.closeStream(os);
IOUtils.closeStream(is);
} return destFile;
} public static void decompress(Path src, Path dest, Configuration config)
throws IOException { LzopCodec codec = new LzopCodec();
codec.setConf(config);
FileSystem hdfs = FileSystem.get(config);
InputStream is = null;
OutputStream os = null; try {
is = codec.createInputStream(hdfs.open(src));
os = hdfs.create(dest);
IOUtils.copyBytes(is, os, config);
} finally {
IOUtils.closeStream(os);
IOUtils.closeStream(is);
}
}
然后写入并读取一个LZOP文件,确保LZOP工具可以操作生成的文件。脚本如下所示:
$ hadoop fs -put $HADOOP_HOME/conf/core-site.xml core-site.xml $ bin/run.sh com.manning.hip.ch5.LzopFileReadWrite core-site.xml
上述代码将在HDFS中生成一个core-site.xml.lzo文件。现在需要确定可以通过lzop程序来处理这个LZOP文件。操作步骤如下:
- 在主机上安装lzop程序。(RedHat和Centos上可以从http://pkgs.repoforge.org/lzop/lzop-1.03-1.el5.rf.x86_64.rpm 安装。)
- 将LZOP文件从HDFS上拷贝到本地磁盘。
- 使用lzop程序解压缩这个LZOP文件。
- 将解压缩后的文件和原始文件进行对比。
操作脚本如下:
$ hadoop fs -get core-site.xml.lzo /tmp/core-site.xml.lzo $ lzop -l /tmp/core-site.xml.lzo method compressed uncompr. ratio uncompressed_name
LZO1X-1 454 954 47.6% core-site.xml $ cd /tmp $ lzop -d core-site.xml.lzo $ ls -ltr -rw-r--r-- 1 aholmes aholmes 954 Sep 11 09:05 core-site.xml
-rw-r--r-- 1 aholmes aholmes 504 Sep 11 09:05 core-site.xml.lzo $ diff core-site.xml $HADOOP_HOME/conf/core-site.xml
$
通过diff程序的比较,说明使用LZOP编码器压缩的文件可以被lzop程序解压缩。然后就需要为LZOP文件建立索引,使它可以被分块。
为LZOP文件创建索引
LZOP支持分块,但是不支持随机访问。这是因为LZOP没有存储每个块的地址信息(地址偏移量)。那么现在需要做的就是创建一个包含LZOP压缩文件中每个块的地址信息(地址偏移量)的索引。创建方法如图5.5所示,遍历一次LZOP的压缩文件,将每个块的地址偏移量保存在索引文件中。索引文件是一个包含了一系列连续的64位的数字。这些数字包含了LZOP压缩文件中每个块的地址偏移量。

有两种方法可以创建索引文件,正如下面的两个代码片段。如果只是要为一个LZOP文件创建一个索引文件,以下就是一个可以完成这个目标的简单库:
shell$ bin/run.sh \
com.hadoop.copmression.lzo.DistributedLzoIndexer \
core.site.xml.lzo \
/path/to/lzop
如果需要批量处理LZOP文件,生成索引,那么就需要更简便的方法。下面这段代码调用一个MapReduce作业来创建索引文件。它通过遍历文件夹中的LZOP文件来支持文件夹作为输入源。也可以以文件作为输入源。
shell$ bin/run.sh \
com.hadoop.copmression.lzo.DistributedLzoIndexer \
core.site.xml.lzo \
/path/to/lzop
前述两段代码都会在LZOP文件的同一个目录下生成一个索引文件。索引文件的文件名是在原LZOP文件名后面加上.index。以上代码会生成文件名为core-site.xml.lzo.index的索引文件。接下来介绍如何在JAVA代码中调用LzoIndexer。以下代码可以同步处理LZOP文件,同步生成索引文件:
LzoIndexer lzoIndexer = new LzoIndexer(new Configuration());
for (String arg: args) {
try {
lzoIndexer.index(new Path(arg));
} catch (IOException e) {
LOG.error("Error indexing " + arg, e);
}
...
通过DistributedLzoIndexer,MapReduce作业将会为每个lzo文件调用一个map任务。不需要reduce任务。Map任务通过自定义的LzoSplitInputFormat和LzoIndexOutputFormat可以直接生成索引文件。如果需要自定义调用MapReduce的JAVA代码,可以参考DistributedLzoIndexer的源代码。
通过前面的代码,为LZOP文件生成了相应的索引文件。接下来介绍如何在MapReduce中使用它们。
MAPREDUCE和LZOP
有了LZOP文件和相应的索引文件之后,就可以在MapReduce中处理LZOP文件了。然而,Hadoop中并没有哪个输入格式直接支持LZOP和它的索引文件。这里就需要为LZOP自定义输入格式类。
以下代码展示了如何在MapReduce作业中处理LZOP。代码可以用来处理文本文件压缩后的LZOP文件。
job.setInputFormatClass(LzoTextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
job.getConfiguration().setBoolean("mapred.output.compress", true);
job.getConfiguration().setClass("mapred.output.compression.codec",
LzopCodec.class, CompressionCodec.class);
另外,压缩map的中间输出也可以提高MapReduce作业的运行速度。代码如下:
conf.setBoolean("mapred.compress.map.output", true);
conf.setClass("mapred.map.output.compression.codec", LzopCodec.class, CompressionCodec.class);
通过配置集群的hdfs-site.xml文件可以总是压缩map的输出:
<property>
<name>mapred.compress.map.output</name>
<value>true</value>
</property>
<property>
<name>mapred.map.output.compression.codec</name>
<value>com.hadoop.compression.lzo.LzopCodec</value>
</property>
需要注意的是,LZOP文件中分块的数量是文件占据的LZOP的块的数量,不是文件占据的HDFS块的数量。
接下来介绍如何在Pig和Hive中处理LZOP。
PIG和HIVE
Elephant Bird是Twitter维护的一个项目,包含处理LZOP的工具。它提供了很多有用的MapReduce和Pig类来处理LZOP。Elephant Bird提供了LzoPigStorage来处理Pig中文本文件的LZOP压缩数据。
Hive可以通过com.hadoop.mapred.DeprecatedLzoTextInputFormat这个输入格式来处理文本文件的LZOP压缩文件。这个输入格式类可以在Todd Lipcon和Kevin Weil的LZO项目中找到。
小结
在Hadoop中处理可分块的压缩数据很有技巧性。如果恰好可以直接用SequenceFiles或Avro来处理数据,那么是再简单不过了。如果一定要压缩并分块,那只能用LZOP了。
正如前面提到的,Elephant Bird项目提供了一些有用的LZOP输入格式来处理LZOP的压缩文件,比如说XML和纯文本的压缩文件。如果你需要处理不被Todd Lipcon的LZO项目和Elephant Bird支持的LZOP的压缩文件格式,就需要自定义输入格式。这对大部分人来说相当困难。期望Hadoop可以早日提供对有特别的分块逻辑的压缩文件的支持,减少开发者的负担。
压缩是所有的生产环境所需要的,因为资源永远稀缺。压缩可以加快执行,减少存储空间。在前面一个章节介绍了如何评价并选择合适的编码器。然后介绍了如何在HDFS,MapReduce,Pig和Hive中使用压缩。最后介绍了如何处理LZOP压缩。
[大牛翻译系列]Hadoop(19)MapReduce 文件处理:基于压缩的高效存储(二)的更多相关文章
- [大牛翻译系列]Hadoop(18)MapReduce 文件处理:基于压缩的高效存储(一)
5.2 基于压缩的高效存储 (仅包括技术25,和技术26) 数据压缩可以减小数据的大小,节约空间,提高数据传输的效率.在处理文件中,压缩很重要.在处理Hadoop的文件时,更是如此.为了让Hadoop ...
- [大牛翻译系列]Hadoop 翻译文章索引
原书章节 原书章节题目 翻译文章序号 翻译文章题目 链接 4.1 Joining Hadoop(1) MapReduce 连接:重分区连接(Repartition join) http://www.c ...
- [大牛翻译系列]Hadoop(17)MapReduce 文件处理:小文件
5.1 小文件 大数据这个概念似乎意味着处理GB级乃至更大的文件.实际上大数据可以是大量的小文件.比如说,日志文件通常增长到MB级时就会存档.这一节中将介绍在HDFS中有效地处理小文件的技术. 技术2 ...
- [大牛翻译系列]Hadoop(1)MapReduce 连接:重分区连接(Repartition join)
4.1 连接(Join) 连接是关系运算,可以用于合并关系(relation).对于数据库中的表连接操作,可能已经广为人知了.在MapReduce中,连接可以用于合并两个或多个数据集.例如,用户基本信 ...
- [大牛翻译系列]Hadoop(5)MapReduce 排序:次排序(Secondary sort)
4.2 排序(SORT) 在MapReduce中,排序的目的有两个: MapReduce可以通过排序将Map输出的键分组.然后每组键调用一次reduce. 在某些需要排序的特定场景中,用户可以将作业( ...
- [大牛翻译系列]Hadoop(10)MapReduce 性能调优:诊断reduce性能瓶颈
6.2.3 Reduce的性能问题 Reduce的性能问题有和map类似的方面,也有和map不同的方面.图6.13是reduce任务的具体的执行各阶段,标识了可能影响性能的区域. 这一章将介绍影响re ...
- [大牛翻译系列]Hadoop(9)MapReduce 性能调优:理解性能瓶颈,诊断map性能瓶颈
6.2 诊断性能瓶颈 有的时候作业的执行时间会长得惊人.想靠猜也是很难猜对问题在哪.这一章中将介绍如何界定问题,找到根源.涉及的工具中有的是Hadoop自带的,有的是本书提供的. 系统监控和Hadoo ...
- [大牛翻译系列]Hadoop(8)MapReduce 性能调优:性能测量(Measuring)
6.1 测量MapReduce和环境的性能指标 性能调优的基础系统的性能指标和实验数据.依据这些指标和数据,才能找到系统的性能瓶颈.性能指标和实验数据要通过一系列的工具和过程才能得到. 这部分里,将介 ...
- [大牛翻译系列]Hadoop(7)MapReduce:抽样(Sampling)
4.3 抽样(Sampling) 用基于MapReduce的程序来处理TB级的数据集,要花费的时间可能是数以小时计.仅仅是优化代码是很难达到良好的效果. 在开发和调试代码的时候,没有必要处理整个数据集 ...
随机推荐
- Xcode代码格式化教程,可自定义样式
来源:iOS_小松哥 链接:http://www.jianshu.com/p/a725e24d7835 为什么要格式化代码 当团队内有多人开发的时候,每个人写的代码格式都有自己的喜好,也可能会忙着写代 ...
- PowerDesigner 之 PDM建模
很多码农使用Powerdesigner用来创建数据库,下面来具体记录一下使用该工具创建的过程. 1.首先运行PowerDesigner程序,进入主界面,如下图: 2.菜单栏依次"File→N ...
- 再识C中的结构体
在前面认识C中的结构体中我介绍了结构体的基础知识,下面通过这段代码来回顾一下: #include<stdio.h> #define LEN 20 struct Student{ //定义结 ...
- Triangular Sums
描述 The nth Triangular number, T(n) = 1 + … + n, is the sum of the first n integers. It is the number ...
- WebApi 部署后一直返回404的解决办法
Fixing ASP.NET MVC 4 Web API 404 Posted on November 5, 2012 For a Web Service providing some REST-st ...
- ubuntu 12.10安装VIM
使用命令:sudo apt-get install vim vim-gtk 可能安装时出错,可用下面更新系统,再执行上面的安装命令. 更新:sudo apt-get update
- [课程相关]homework-09
零.前言 这次的作业比较特殊,有两种做法.由于我对网页很熟悉,所以选择网页. 细节不赘述,下面写一下这次作业的几个亮点. 一.亮点 最大的亮点就是这个页面是纯客户端的,没有服务端.也就是说所有功能都是 ...
- 05. 取SQL分组中的某几行数据
对表中数据分组,有时只需要某列的聚合值:有时却需要返回整行数据,常用的方法有:子查询.ROW_NUMBER.APPLY,总体感觉还是ROW_NUMBER比较直观.测试数据: if OBJECT_ID( ...
- javascript组件开发
最近忙于重构项目,今天周末把在重构中的一些思想记记: 一.javascript的组件开发:基类的封装 由于这次重构项目需要对各种组件进行封装,并且这些组件的实现方式都差不多,所以想到对组件封装一个ba ...
- 转:关于视频H264编解码的应用实现
转:http://blog.csdn.net/scalerzhangjie/article/details/8273410 项目要用到视频编解码,最近半个月都在搞,说实话真是走了很多弯路,浪费了很多时 ...