探索Hadoop OutputFormat_Hadoop,ERP及大数据讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Hadoop,ERP及大数据讨论区 »
总帖数
2
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3150 | 回复: 1   主题: 探索Hadoop OutputFormat        上一篇   下一篇 
flying
注册用户
等级:下士
经验:153
发帖:75
精华:0
注册:2011-8-25
状态:离线
发送短消息息给flying 加好友    发送短消息息给flying 发消息
发表于: IP:您无权察看 2016-3-28 18:00:39 | [全部帖] [楼主帖] 楼主

Hadoop常常被用作大型数据处理生态系统中的一部分。它的优势在于能够批量地处理大量数据,并将结果以最好的方式与其他系统相集成。从高层次角度来看,整个过程就是Hadoop接收输入文件、使用自定义转换(Map-Reduce步骤)获得内容流,以及将输出文件的结果写回磁盘。在本文中,我们将同大家一起探讨怎样自定义最后一 个步骤——即怎样写入输出文件。OutputFormat将Map/Reduce作业的输出结果转换为其他应用程序可读的方式,从而轻松实现与其他系统的互操作。为了展示OutputFormts的实用性,将用两个例子进行讨论:如何拆分作业结果到不同目录以及如何为提供快速键值查找的服务写入文件。

OutputFormt 接口决定了在哪里以及怎样持久化作业结果。Hadoop为不同类型的格式提供了一系列的类和接口,实现自定义操作只要继承其中的某个类或接口即可。你可能 已经熟悉了默认的OutputFormat,也就是TextOutputFormat,它是一种以行分隔,包含制表符界定的键值对的文本文件格式。尽管如此,对多数类型的数据而言,如再常见不过的数字,文本序列化会浪费一些空间,由此带来的结果是运行时间更长且资源消耗更多。为了避免文本文件的弊端,Hadoop提供了SequenceFileOutputformat,它将对象表示成二进制形式而不再是文本文件,并将结果进行压缩。下面是 Hadoop提供的类层次结构:

  • FileOutputFormat(实现OutputFormat接口)—— 所有OutputFormats的基类

    • MultipleTextOutputFormat —— 输出多个以标准行分割、制表符定界格式的文件

    • MultipleSequenceFileOutputFormat —— 输出多个压缩格式的文件

    • SequenceFileAsBinaryOutputFormat —— 原生二进制数据的压缩格式

    • MapFileOutputFormat —— 一种使用部分索引键的格式

    • SequenceFileOutputFormat —— 二进制键值数据的压缩格式

    • TextOutputFormat —— 以行分隔、包含制表符定界的键值对的文本文件格式

    • MultipleOutputFormat —— 使用键值对参数写入文件的抽象类

OutputFormat提供了对RecordWriter的实现,从而指定如何序列化数据。 RecordWriter类可以处理包含单个键值对的作业,并将结果写入到OutputFormat中准备好的位置。RecordWriter的实现主要包括两个函数:“write”和“close”。“write”函数从Map/Reduce作业中取出键值对,并将其字节写入磁盘。 LineRecordWriter是默认使用的RecordWriter,它是前面提到的TextOutputFormat的一部分。它写入的内容包括:

  • 键(key)的字节 (由getBytes()函数返回)

  • 一个用以定界的制表符

  • 值(value)的字节(同样由getBytes()函数返回)

  • 一个换行符

“close”函数会关闭Hadoop到输出文件的数据流。

我们已经讨论了输出数据的格式,下面我们关心的问题是数据存储在何处?同样,你或许看到过某个作业的输出结果会以多个“部分”文件的方式存储在输出目录中,如下:

|-- output-directory
| |-- part-00000
| |-- part-00001
| |-- part-00002
| |-- part-00003
| |-- part-00004
'-- part-00005

默认情况下,当需要写入数据时,每个进程都会在输出目录创建自己的文件。数据由reducers在作业结束时写入(如果没有 reducers会由mapper写入)。即使在本文后面提到的创建自定义输出目录时,我们仍会保持写入“部分”文件,这么做可以让多个进程同时写入同一 个目录而互不干扰。

自定义OutputFormat

从前面已经看到,OutputFormat类的主要职责是决定数据的存储位置以及写入的方式。那么为什么要自定义这些行为呢?自定义数据位置的原因之一是为了将Map/Reduce作业输出分离到不同的目录。例如,假设需要处理 一个包含世界范围内的搜索请求的日志文件,并希望计算出每个国家的搜索频度。想要在不牵涉其他国家的前提下能够查看某个特定国家的结果。也许以后在你的数据管道中,会用不同的进程来处理不同的国家,或者想要把某个特定国家的结果复制一份到该国的数据中心去。使用默认的OutputFormat时,所有的数据都会存储在同一目录下,这样在不浏览的情况下是无从知晓“部分”文件的内容的。而通过使用自定义的OutputFormat,可以为每个国家创建一 个子目录的布局,如下:

|-- output-directory
|   |-- France
|   |   |-- part-00000
|   |   |-- part-00001
|   |   '-- part-00002
... |
|   '-- Zimbabwe
|       |-- part-00000
|       |-- part-00001
|       '-- part-00002

其中每个部分文件都具有键值对(“搜索词汇”=>频度)。现在只要简单地指定某个国家数据所在的路径,就可以只读取该国家的数据了。下面我们将看到怎样继承MultipleTextOutputFormat类,以获得所需的行为。

自定义OutputFormat还有一些其他的原因,以名为ElephantDB的项目为例, 它将数据以一种面向消费应用程序的“本地”形式进行存储。这个项目的设立是为了让Map/Reduece作业结果可以像分布式服务一样被查询。 ElephantDB写入的并不是文本文件,而是使用自定义的OutputFormat将结果写成BerkeleyDB文件,其中这些文件使用作业输出的键进行索引。之后使用某个服务加载BerkeleyDB文件,可以提供低延滞的任意键查找。类似的系统还有HBase和Voldemort,它们可以存储Hadoop生成的键值数据。ElephantDB重点关注的是怎样与Hadoop批量式更新进行简易紧密的集成。

多路输出

为了解决上面的搜索日志的问题,我们继承了MultipleTextOutputFormat类,并根据被写入的键值来选择输出目录。我们的Map/Reduce作业将会为搜索请求所在国家生成一个键,并为搜索词汇及该搜索的频度产生一个值。由于 MultipleTextOutputFormat已经知道如何写入文本文件,因此并不需要为OutputFormat实现序列化功能。清单1实现了该 类:

1 package oddjob.hadoop;
2
3 import org.apache.hadoop.fs.Path;
4 import org.apache.hadoop.io.Text;
5 import org.apache.hadoop.mapred.lib.MultipleTextOutputFormat;
6
7 public class MultipleTextOutputFormatByKey extends MultipleTextOutputFormat<Text, Text> {
8
9        /**
10        * Use they key as part of the path for the final output file.
11        */
12       @Override
13       protected String generateFileNameForKeyValue(Text key, Text value, String leaf) {
14             return new Path(key.toString(), leaf).toString();
15       }
16
17       /**
18        * When actually writing the data, discard the key since it is already in
19        * the file path.
20        */
21       @Override
22       protected Text generateActualKey(Text key, Text value) {
23             return null;
24          }
25 }




--转自



赞(0)    操作        顶端 
美炸了的菇凉
注册用户
等级:上士
经验:315
发帖:0
精华:0
注册:2016-2-17
状态:离线
发送短消息息给美炸了的菇凉 加好友    发送短消息息给美炸了的菇凉 发消息
发表于: IP:您无权察看 2016-3-29 19:36:10 | [全部帖] [楼主帖] 2  楼

学到了!谢谢楼主



赞(0)    操作        顶端 
总帖数
2
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论