使用输入拆分(hadoop)

xtfmy6hx  于 2021-05-29  发布在  Hadoop
关注(0)|答案(2)|浏览(369)

我有一个 .txt 文件如下:
我是xyz
这是我的家
这是我的电脑
这是我的房间
这是ubuntu pc
(忽略每条记录后的空行)
我已将块大小设置为64字节。我想检查的是,是否存在一条记录被分成两个块的情况。
现在从逻辑上讲,由于块大小是64字节,所以在将文件上载到hdfs之后,它应该分别创建3个大小为64、64、27字节的块,它确实如此。此外,由于第一个块的大小为64字节,因此它应仅包含以下数据:
我是xyz
这是我的家
这是我的电脑
这是我的房间

现在我想看看第一个块是否像这样,如果我通过浏览器浏览hdfs并下载文件,它会下载整个文件而不是单个块。
所以我决定运行一个map reduce作业,它只显示记录值 reducers=0 ,Map器输出为 context.write(null,record_value) ,同时将默认分隔符更改为 "" )
现在,在运行作业时,作业计数器显示3个拆分,这是显而易见的,但是在完成后,当我检查输出目录时,它显示3个Map器输出文件,其中2个是空的,第一个Map器输出文件具有文件的所有内容。
有人能帮我吗?新版本的hadoop是否有可能自动处理不完整的记录?

rbpvctlc

rbpvctlc1#

复制场景所遵循的步骤
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

2) 已将属性添加到 `hdfs-site.xml` ```
<property>
    <name>dfs.namenode.fs-limits.min-block-size</name>
    <value>10</value>
</property>

并加载到块大小为 64B .

hdfs dfs -Ddfs.bytes-per-checksum=16 -Ddfs.blocksize=64 -put sample.txt /

这就产生了三个大小块 64B , 64B 以及 25B .
内容 Block0 :

This is xyz
This is my home
This is my PC
This is my room
This i

内容 Block1 :

s ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx

内容 Block2 :

xx xxxxxxxxxxxxxxxxxxxxx

3) 一个简单的 mapper.py ```

!/usr/bin/env python

import sys

for line in sys.stdin:
print line

4) hadoop流媒体 `0` 异径管:

yarn jar hadoop-streaming-2.7.1.jar -Dmapreduce.job.reduces=0 -file mapper.py -mapper mapper.py -input /sample.txt -output /splittest

作业运行时使用3个输入拆分调用3个Map器,并生成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

文件 `sample.txt` 被分成3个部分,这些部分被分配给每个Map器,

mapper1: start=0, length=64B
mapper2: start=64, length=64B
mapper3: start=128, length=25B

这只决定了Map程序必须读取文件的哪一部分,而不一定要精确。Map程序读取的实际内容由fileinputformat及其边界决定 `TextFileInputFormat` .
它使用 `LineRecordReader` 从每次拆分中读取内容并使用 `\n` 作为分隔符(线边界)。对于未压缩的文件,每个Map器都会读取这些行,如下所述。
对于起始索引为0的Map器,行读取从拆分的起始处开始。如果分裂以 `\n` 读数在分割边界处结束,否则将查找第一个边界 `\n` 张贴分配的拆分长度(此处 `64B` ). 这样它就不会处理部分行。
对于所有其他Map器(开始索引!=0),它检查前一个字符是否从其起始索引( `start - 1` )是 `\n` ,如果是,则从拆分的开始处读取内容,否则将跳过在其开始索引和第一个索引之间存在的内容 `\n` 在该拆分中遇到的字符(因为此内容由其他Map程序处理),并从第一个开始读取 `\n` . 
在这里, `mapper1` (起始索引为0)起始于 `Block0` 在一条线的中间。因此,它继续读取消耗整个 `Block1` 从那以后呢 `Block1` 没有一个 `\n` 性格, `mapper1` 继续阅读直到找到 `\n` 以消耗整个 `Block2` 也。这就是 `sample.txt` 最终以单个Map器输出结束。 `mapper2` (开始索引!=0),其开始索引之前的一个字符不是 `\n` ,所以跳过这一行,最终没有内容。空Map器输出。 `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

u2nhd7ah

u2nhd7ah2#

使用以下命令获取hdfs上文件的阻止列表
hdfs fsck path-文件-块-位置
where path是文件所在的完整hdfs路径。
输出(部分如下所示)将是这样的(行号2,3。。。忽略)
通过连接到namenodehttp://ec2-54-235-1-193.compute-1.amazonaws.com:50070/fsck?ugi=student6&files=1&blocks=1&locations=1&path=%2fsudent6%2ftest.txt fsck由student6启动(auth:simple)自/172.31.11.124起,路径为/student6/test.txt,时间为2017年3月22日星期三15:33:17 utc/student6/test.txt,22字节,1个块:确定0。bp-944036569-172.31.11.124-1467635392176:blk\ U 1073755254\ U 14433 len=22 repl=1[数据节点信息存储[172.31.11.124:50010,ds-4a530a72-0495-4b75-a6f9-75bdb8ce7533,磁盘]]
复制输出命令的粗体部分(不包括),如上面的输出示例所示
转到datanode上的linux文件系统到存储块的目录(这将由hdfs-site.xml的dfs.datanode.data.dir参数指向),并从该位置在整个子树中搜索包含刚才复制的粗体字符串的文件名。这将告诉您dfs.datanode.data.dir下的哪个子目录包含名称中带有该字符串的文件(排除任何带有.meta后缀的文件名)。一旦找到这样的文件名,就可以对该文件名运行linux cat命令来查看文件内容。
请记住,尽管该文件是一个hdfs文件,但在封面下,该文件实际上存储在linux文件系统中,hdfs文件的每个块都是一个惟一的linux文件。该块由linux文件系统标识,其名称如步骤2的粗体字符串所示

相关问题