整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

7.2.2. 文本输入 7.2.2.1. TextlnputFormat

hadoop 花牛 8℃ 0评论

Hadoop非常擅长处理非结构化文本数据。本节讨论Hadoop提供的用于处理文本的不同InputFormat类。

TextlnputFormat是默认的InputFormat。每条记录是一行输入。键是 LongWritable类型,存储该行在整个文件中的字节偏移量。值是这行的内容,不包括任何行终止符(换行符和回车符),它被打包成一个Text对象。所以,包含如下文本的文件被切分为包含4条记录的一个分片:

On the top of the Crumpetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beaver Hat.

每条记录表示为以下键/值对:

(0, On the top of the Crumpetty Tree)

(33, The Quangle Wangle sat,)

(57, But his face you could not see,)

(89, On account of his Beaver Hat.)

很明显,键并不是行号。一般情况下,很难取得行号,因为文件按字节而不是按行切分为分片。每个分片单独处理。行号实际上是一个顺序的标记,即每次读取一行的时候需要对行号进行计数。因此,在分片内知道行号是可能的,但在文件中是不可能的。

然而,每一行在文件中的偏移量是可以在分片内单独确定的,而不需要知道分片的信息,因为每个分片都知道上一个分片的大小,只需要加到分片内的偏移量上,就可以获得每行在整个文件中的偏移量了。通常,对于每行需要唯一标识的应用来说,有偏移量就足够了。如果再加上文件名,那么它在整个文件系统内就是唯一的。当然,如果每一行都是定长的,那么这个偏移量除以每一行的长度即可算出行号。

输入分片与HDFS块之间的关系

FilelnputFormat定义的逻辑记录有时并不能很好地匹配HDFS的文件块。例如,TextlnputFormat的逻辑记录是以行为单位的,那么很有可能某一行会跨文件块存放。虽然这对程序的功能没有什么影响,如行不会丢失或出错,但这种现象应该引起注意,因为这意味着那些“本地的”map(map运行在输入数据所在的主机上)会执行一些远程的读操作。由此而来的额外开销一般不是特别明显。 图7-3展示了一个例子。一个文件被分成几行,行的边界与HDFS块的边界没有对齐。分片的边界与逻辑记录的边界对齐,这里是行边界,所 以第一个分片包含前5行,即使第5行跨了第一块和第二块。第二个分片从第6行开始。

blob.png 

图7-3. TextlnputFormat的逻辑记录和HDFS

2.2.2. 关于 KeyValueTextlnputFormat

TextlnputFormat的键,即每一行在文件中的字节偏移量,通常并不是特别有用。通常情况下,文件中每一行是一个键/值对,使用某个分界符进行分隔,比如制表符。例如以下由Hadoop默认OutputFormat(TextOutputFormat)产生的输出。如果要正确处理这类文件, KeyValueTextlnputFormat 比较合适。

可以通过mapreduce.input. keyvaluelinerecordreader.key.value.separator属性(或者老版本API中的key.value.separator.in.input.line属性)来指定分隔符。它的默认值是一个制表符。以下是一个范例,其中表示一个(水平方向的)制表符:

line1On the top of the Crumpetty Tree

line2—The Quangle Wangle sat,

Iine3But his face you could not see,

line4—On account of his Beaver Hat.

与TextlnputFormat类似,输入是一个包含4条记录的分片,不过此时的键是每行排在制表符之前的Text序列:

(line1, On the top of the Crumpetty Tree)

(line2, The Quangle Wangle sat,)

(line3, But his face you could not see,)

(line4, On account of his Beaver Hat.)

2.2.3. 关于NLinelnputFormat

通过TextlnputFormat 和 KeyValueTextlnputFormat每个mapper收到的输入行数不同。行数取决于输入分片的大小和行的长度。如果希望mapper收到固定行数的输入,需要将NLinelnputFormat作为InputFormat。与TextlnputFormat—样,键是文件中行的字节偏移量,值是行本身。

N是每个mapper收到的输入行数。N设置为1(默认值)时,每个mapper正好收到一行输入。mapreduce.input.lineinputformat.linespermap属性(在老版本API中的mapred.line.input.format.linespermap属性)实现N值的设定。仍然以刚才的4行输入为例:

On the top of the Crumpetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beaver Hat.

例如,如果N是2,则每个输入分片包含两行。一个mapper收到前两行键/值对:

(0, On the top of the Crumpetty Tree)

(33, The Quangle Wangle sat,)

另一个mapper则收到后两行:

(57, But his face you could not see,)

(89, On account of his Beaver Hat.)

键和值与TextlnputFormat生成的一样。不同的是输入分片的构造方法。

通常来说,对少量输入行执行map任务是比较低效的(任务初始化的额外开销造成的),但有些应用程序会对少量数据做一些扩展的(也就是CPU密集型的)计算任务,然后产生输出。仿真是一个不错的例子。通过生成一个指定输入参数的输入文件,每行一个参数,便可以执行一个参数扫描分析 (parameter sweep):并发运行一组仿真试验,看模型是如何随参数不同而变化的。

在一些长时间运行的仿真实验中,可能会出现任务超时的情况。一个任务在10分钟内没有报告状态,tasktracker就会认为任务失败,进场止进程(参£ 6.2.1节娜细讨论)

这个问题最佳解决方案是定期报告状态,如写一段状态信息,或增加计数器的值。详情可以参见6.1节的补充材料“MapReduce中进度的组成”。

另一个例子是用Hadoop引导从多个数据源(如数据库)加载数据。创建一个“种子”输入文件,记录所有的数据源,一行一个数据源。然后每个mapper分到一个数据源,并从这些数据源中加载数据到HDFS中。这个作业不需要reduce阶段,所以reducer的数量应该被设成0(通过调用Job的setNumReduceTasks()来设置)。MapReduce作业就可以处理加载到HDFS中的数据。

2.2.4. 关于XML

大多数XML解析器会处理整个XML文档,所以如果一个大型XML文档由多个输入分片组成,那么单独解析每个分片就相当有挑战。当然,可以在一个mapper(如果这个文件不是很大),可以使用7.2.1节介绍的方法来处理整个XML文档。

由很多“记录”(此处是XML文档片断)组成的XML文档,可以使用简单的字符串匹配或正则表达式匹配的方法来查找记录的开始标签和结束标签,而得到很多记录。这可以解决由MapReduce框架进行分割的问题,因为一条记录的下一个开始标签可以通过简单地从分片开始处进行扫描轻松找到,就像TextlnputFormat确定新行的边界一样。

Hadoop提供了StreamXmlRecordReader(org.apache.hadoop.streaming包中,还可以在Streaming之外使用)。通过把输入格式设置为StreamlnputFormat,把stream.recordreader.class 属性设置为org.apache.Hadoop.Streaming.StreamXmlRecordReader来使用StreamXmlRecordReader类。reader的配置方法是通过作业配置属性来设置reader开始标签和结束标签(详情参见该类的帮助文档)

例如,维基百科用XML格式来提供大量数据内容,非常适合用MapReduce来并行处理。数据包含在一个大型的XML打包文档中,文档中有一些元素,例如包含每页内容和相关元数据的page元素。使用streamXmlRecordReader后,这些page元素便可解释为一系列的记录,交由一个mapper来处理。

转载请注明:全栈大数据 » 7.2.2. 文本输入 7.2.2.1. TextlnputFormat

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址