破解Mapreduce找不到文件坑点所在(分布式部署)

636 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

你的mapreduce代码中是否有出现过类似这样的问题:

subprocess failed with code2

unkown file or dir..

为什么?

这就需要我们来了解一下Hadoop的数据存储和工作机制。

运算意义上,Hadoop中有两种节点:jobtracker和tasktracker
存储意义上,集群中有两种东西:HDFS和本地的文件系统

为什么你有时候写代码就会出现以上两个错误,明明感觉引用的东西都正确了,但是就是说找不到这个文件??

大概率就是你没有再运行的时候分清楚到底是那个文件,哪个环境,在哪个系统之下.

如果这个没有分清楚,写分布式的bash简直遍地都是坑。(亲身经历)

OIP.jpg

让我们从一段简单的bash开始(我用的是hadoop2.7.3)

HADOOP_CMD='/usr/hadoop/hadoop-2.7.3/bin/hadoop'
STREAM_JAR_PATH='/usr/hadoop/hadoop-2.7.3/share/hadoop/tools/lib/hadoop-streaming-2.7.3.jar'
INPUT_PATH='/data.txt'
OUTPUT_PATH='quchongtongxue'
PYTHON_PATH='/root/anaconda3/bin/python3'

${HADOOP_CMD} fs -rm -r /input/${OUTPUT_PATH}
$HADOOP_CMD jar $STREAM_JAR_PATH \
	-input  $INPUT_PATH  \
	-output  "/input/${OUTPUT_PATH}" \
	-mapper "$PYTHON_PATH  ${OUTPUT_PATH}.py map" \
	-reducer "$PYTHON_PATH ${OUTPUT_PATH}.py reduce" \
    -file "/home/${OUTPUT_PATH}.py"

这个bash中指定了一些参数,其中大多数是文件的位置。

错误一:unkown file or dir..

出现类似的问题大概是没有在hadoop执行的bash后面加上-file这段文字
为什么?因为在hadoop2的时候不会到本地寻找文件,需要你特别指定好之后,才会把-file中指定的本地文件上传到HDFS的缓存或者cache中。如果没有指定,HDFS上的缓存当然是找不到的。

错误2:subprocess failed with code2

出现这个问题的主要原因大概就是没有分清楚HDFS文件系统的工作原理和服务器本身的文件系统之间的关系。
为什么会有HDFS?
这就要从我最初的Mapreduce中说起。你想要运行一段代码有如下步骤:
1.你在你的本机上写好代码
2.上传至HDFS上,并由HDFS分发文件给不同的机器
3.开始计算:由JobTRACKER分配任务给tasktracker,让其开始工作

看到这里,你可能会有问题:

1.为什么一定要上传到HDFS上?不直接在本机上进行运算?
原因很简单,文件是可以通过操作系统和网络进行分发,相当于是可以传导的,但是如果把这个文件只是存储在本机上,别的机器的算力却没有办法通过这样的方式把算力发送过来。
2.那么,在代码计算的时候,可以不计算HDFS上的文件吗?(此处是-input data.txt)
首先,你需要确认你使用的解释器安装在哪里。
HDFS就像是一个真正的文件系统,你可以在上面构建许多东西,甚至可以使用-cacheArchive来指定HDFS上的python环境。这样的话你所使用的数据就需要全部都在HDFS上了。。
其次,如果你的解释器安装在服务器本地(这样每台服务器都需要装相同位置的环境),上文的bash中的-input中的数据必须是已经上传到HDFS中的,不能写一段本地的路径。那么,怎么计算存储在本地的数据?你需要每个服务器上都存储一份相同的,然后在代码中指定文件位置进行计算。

所以为什么会出现上文中failed with code2这个问题?
1)首先,你的代码会被-file送到HDFS上。
2)然后,-mapper里面会去文件那里寻找 ${OUTPUT_PATH},如果你写的是/home/a.py(物理机上的文件位置)而不是a.py,会让mapreduce在HDFS中找不到文件,然后导致这个错误

错误3:unkwon file python

你找不到python,很简单,在mapper和reducer前面都指定一下$PYTHON_PATH就可以(这里是本地的,无需python文件位置,但是需要你的每台机器上都有python环境,并且位置相同;如果想用HDFS上的环境,请使用-cacheArchive参数)

-mapper "$PYTHON_PATH  ${OUTPUT_PATH}.py map" \
	-reducer "$PYTHON_PATH ${OUTPUT_PATH}.py reduce" \

以上就是个人的一些观点,如果有错误希望大家能指正一下。谢谢。