使用输入拆分(HADOOP)

Use*_*523 10 hadoop mapreduce hadoop2

我有一个.txt文件如下:


这是xyz

这是我的家

这是我的电脑

这是我的房间

这是ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx


(忽略每条记录后的空白行)

我已将块大小设置为64字节.我要检查的是,是否存在单个记录被分成两个块的情况.

现在逻辑上,因为块大小是64字节,在将文件上传到HDFS之后,它应该分别创建3块大小为64,64,27字节的块.此外,由于第一个块的大小为64字节,因此它应仅包含以下数据:


这是xyz

这是我的家

这是我的电脑

这是我的房间


现在我想看看第一个块是否是这样,如果我通过浏览器浏览HDFS并下载文件,它会下载整个文件而不是单个块.

所以我决定运行一个map-reduce作业,它只显示记录值.(设置reducers=0和mapper输出为context.write(null,record_value),也改变默认分隔符"")

现在,在运行作业时,作业计数器显示3个拆分,这是显而易见的,但在检查输出目录完成后,它显示3个映射器输出文件,其中2个为空,第一个映射器输出文件具有所有内容文件原样.

谁能帮我这个?新版本的hadoop是否有可能自动处理不完整的记录?

fra*_*ijo 7

重现场景的步骤
1)创建一个sample.txt包含总大小的内容的文件~153B

cat sample.txt

This is xyz
This is my home
This is my PC
This is my room
This is ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxxxxxxxxxxxxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

2)添加属性hdfs-site.xml

<property>
    <name>dfs.namenode.fs-limits.min-block-size</name>
    <value>10</value>
</property>
Run Code Online (Sandbox Code Playgroud)

并以块大小加载到HDFS中64B.

hdfs dfs -Ddfs.bytes-per-checksum=16 -Ddfs.blocksize=64 -put sample.txt /
Run Code Online (Sandbox Code Playgroud)

这创造了三个大小的块64B,64B25B.

内容Block0:

This is xyz
This is my home
This is my PC
This is my room
This i
Run Code Online (Sandbox Code Playgroud)

内容Block1:

s ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx
Run Code Online (Sandbox Code Playgroud)

内容Block2:

xx xxxxxxxxxxxxxxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

3)简单mapper.py

#!/usr/bin/env python

import sys

for line in sys.stdin:
    print line
Run Code Online (Sandbox Code Playgroud)

4) Hadoop Streaming with 0reducer:

yarn jar hadoop-streaming-2.7.1.jar -Dmapreduce.job.reduces=0 -file mapper.py -mapper mapper.py -input /sample.txt -output /splittest
Run Code Online (Sandbox Code Playgroud)

作业运行3个输入拆分调用3个映射器并生成3个输出文件,其中一个文件包含整个内容sample.txt和其余0B文件.

hdfs dfs -ls /splittest

-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/_SUCCESS
-rw-r--r--   3 user supergroup        168 2017-03-22 11:13 /splittest/part-00000
-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/part-00001
-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/part-00002
Run Code Online (Sandbox Code Playgroud)

该文件sample.txt被拆分为3个拆分,这些拆分分配给每个映射器,如,

mapper1: start=0, length=64B
mapper2: start=64, length=64B
mapper3: start=128, length=25B
Run Code Online (Sandbox Code Playgroud)

这仅确定映射器必须读取文件的哪个部分,而不必必须精确.映射器读取的实际内容由FileInputFormat及其边界决定TextFileInputFormat.

这用于LineRecordReader从每个拆分中读取内容并\n用作分隔符(行边界).对于未压缩的文件,每个映射器读取行,如下所述.

对于起始索引为0的映射器,行读取从拆分开始开始.如果分割结束时\n读数结束于分割边界,则它会查找第一个\n帖子分配的分割长度(此处64B).这样它不会最终处理部分线.

对于所有其他映射器(起始索引!= 0),它检查前面的字符是否来自其起始索引(start - 1)\n,如果是,它从分割开始读取内容,否则它会跳过其起始之间存在的内容index和该\n分割中遇到的第一个字符(因为此内容由其他映射器处理)并从第一个开始读取\n.

这里,mapper1(起始索引为0)开始,Block0其分割结束在一行的中间.因此,它继续读取消耗整个行Block1并且由于Block1没有\n字符的行mapper1继续读取,直到找到\n以消耗整个为止的那一行结束Block2.这就是整个内容sample.txt在单个映射器输出中的结果.

mapper2(起始索引!= 0),其起始索引之前的一个字符不是a \n,因此跳过该行并最终没有内容.空映射器输出.mapper3具有相同的情景mapper2.


尝试更改sample.txt此类内容以查看不同的结果

This is xyz
This is my home
This is my PC
This is my room
This is ubuntu PC xxxx xxxx xxxx xxxx 
xxxx xxxx xxxx xxxx xxxx xxxx xxxx 
xxxxxxxxxxxxxxxxxxxxx
Run Code Online (Sandbox Code Playgroud)