在Ubuntu虚拟机上,我根据Michael Noll的tutorial建立了一个单节点集群,这是我编写Hadoop程序的起点。
另外,作为参考,this。
我的程序是使用Python并使用Hadoop Streaming。
我编写了一个简单的向量乘法程序,其中mapper.py
采用输入文件v1
和v2
,每个文件都包含12,33,10
形式的向量并返回产品。然后reducer.py
返回产品的总和,即:
映射器:map(mult,v1,v2)
reducer :sum(p1,p2,p3,...,pn)
mapper.py:
import sys
def mult(x,y):
return int(x)*int(y)
# Input comes from STDIN (standard input).
inputvec = tuple()
for i in sys.stdin:
i = i.strip()
inputvec += (tuple(i.split(",")),)
v1 = inputvec[0]
v2 = inputvec[1]
results = map(mult, v1, v2)
# Simply printing the results variable would print the tuple. This
# would be fine except that the STDIN of reduce.py takes all the
# output as input, including brackets, which can be problematic
# Cleaning the output ready to be input for the Reduce step:
for o in results:
print ' %s' % o,
reducer.py:
import sys
result = int()
for a in sys.stdin:
a = a.strip()
a = a.split()
for r in range(len(a)):
result += int(a[r])
print result
在in
子目录中,我v1
包含5,12,20
和v2
,其中包含14,11,3
。
在本地测试,事情按预期工作:
hduser@ubuntu:~/VectMult$ cat in/* | python ./mapper.py
70 132 60
hduser@ubuntu:~/VectMult$ cat in/* | python ./mapper.py | sort
70 132 60
hduser@ubuntu:~/VectMult$ cat in/* | python ./mapper.py | sort | python ./reducer.py
262
当我在Hadoop中运行它时,它似乎成功完成并且不会抛出任何异常:
hduser@ubuntu:/usr/local/hadoop$ bin/hadoop jar contrib/streaming/hadoop-*streaming*.jar -mapper python /home/hduser/VectMult3/mapper.py -reducer python /home/hduser/VectMult3/reducer.py -input /home/hduser/VectMult3/in -output /home/hduser/VectMult3/out4
Warning: $HADOOP_HOME is deprecated.
packageJobJar: [/app/hadoop/tmp/hadoop-unjar2168776605822419867/] [] /tmp/streamjob6920304075078514767.jar tmpDir=null
12/11/18 21:20:09 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/11/18 21:20:09 WARN snappy.LoadSnappy: Snappy native library not loaded
12/11/18 21:20:09 INFO mapred.FileInputFormat: Total input paths to process : 2
12/11/18 21:20:09 INFO streaming.StreamJob: getLocalDirs(): [/app/hadoop/tmp/mapred/local]
12/11/18 21:20:09 INFO streaming.StreamJob: Running job: job_201211181903_0009
12/11/18 21:20:09 INFO streaming.StreamJob: To kill this job, run:
12/11/18 21:20:09 INFO streaming.StreamJob: /usr/local/hadoop/libexec/../bin/hadoop job -Dmapred.job.tracker=localhost:54311 -kill job_201211181903_0009
12/11/18 21:20:09 INFO streaming.StreamJob: Tracking URL: http://localhost:50030/jobdetails.jsp?jobid=job_201211181903_0009
12/11/18 21:20:10 INFO streaming.StreamJob: map 0% reduce 0%
12/11/18 21:20:24 INFO streaming.StreamJob: map 67% reduce 0%
12/11/18 21:20:33 INFO streaming.StreamJob: map 100% reduce 0%
12/11/18 21:20:36 INFO streaming.StreamJob: map 100% reduce 22%
12/11/18 21:20:45 INFO streaming.StreamJob: map 100% reduce 100%
12/11/18 21:20:51 INFO streaming.StreamJob: Job complete: job_201211181903_0009
12/11/18 21:20:51 INFO streaming.StreamJob: Output: /home/hduser/VectMult3/out4
hduser@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -cat /home/hduser/VectMult3/out4/part-00000
Warning: $HADOOP_HOME is deprecated.
hduser@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -ls /home/hduser/VectMult3/out4/
Warning: $HADOOP_HOME is deprecated.
Found 3 items
-rw-r--r-- 1 hduser supergroup 0 2012-11-18 22:05 /home/hduser/VectMult3/out4/_SUCCESS
drwxr-xr-x - hduser supergroup 0 2012-11-18 22:05 /home/hduser/VectMult3/out4/_logs
-rw-r--r-- 1 hduser supergroup 0 2012-11-18 22:05 /home/hduser/VectMult3/out4/part-00000
但是当我检查输出时,我找到的只是一个0字节的空文件。
我无法弄清楚出了什么问题。有人可以帮忙吗?
编辑:对@DiJuMx的回应
解决此问题的一种方法是从map输出到临时文件,然后在reduce中使用临时文件。
不确定Hadoop是否允许这样做?希望知道更好的人可以纠正我。
在尝试此操作之前,请尝试编写一个更简单的版本,只需直接传递数据而无需处理。
我认为这是一个好主意,只是为了检查数据是否正确流过。我使用了以下内容:
mapper.py和reducer.py
import sys
for i in sys.stdin:
print i,
出现的内容应该是正确的内容。仍然输出一个空文件。
或者,如果输入为空白,则在reduce中编辑现有代码以将(错误)消息输出到输出文件
mapper.py
import sys
for i in sys.stdin:
print "mapped",
print "mapper",
reducer.py
import sys
for i in sys.stdin:
print "reduced",
print "reducer",
如果收到输入,则最终应输出reduced
。无论哪种方式,它至少应该输出reducer
。实际输出仍为空文件。
答案 0 :(得分:0)
我没有任何关于hadoop(或python)的经验,但是,我注意到的是你指定输出转到/home/hduser/VectMult3/out4
但期望它在{{1} }。
您是否检查过/home/hduser/VectMult3/out/part-00000
文件是否存在及其内容是什么?
答案 1 :(得分:0)
假设你的代码是完全正确的(如我所假设的问题的第一部分所示),问题可以缩小到你工作的环境。在这种情况下,我会说它是因为映射器的输出没有通过管道输入到reducer中(就像手动运行命令时那样)
解决此问题的一种方法是从map输出到临时文件,然后在reduce中使用临时文件。
在尝试此操作之前,请尝试编写一个更简单的版本,只需直接传递数据而无需处理。如果仍然没有得到任何结果,请尝试临时文件。
或者,如果输入为空,则在reduce中编辑现有代码以将(错误)消息输出到输出文件
答案 2 :(得分:0)
我知道这个问题相当陈旧,但我还是想帮忙。我在你的reducer.py和mapper.py示例中看到,你只是输出一个值。我相信(我刚开始使用Hadoop,但这是我迄今为止的经验),它需要一个由标签分隔的键值对。
例如,您的映射器输出可能与此类似:
print "%s\t%s" % (str(random.randint(0,100000)), "mapped")
我不确定但减速器可能输出任何东西。如果仍然无法工作,请按照此博客http://www.michael-noll.com/tutorials/writing-an-hadoop-mapreduce-program-in-python/上的说明创建一个测试用例,它在我的环境中工作,所以希望它能为您做同样的事情。如果此示例不起作用,则很可能是您的Hadoop设置存在问题。
答案 3 :(得分:0)
您是否尝试将python mapper.py
替换为"python mapper.py"
?我认为映射器运行python
而不是python mapper.py
。它可以解释你的空输出。
此外,您的文件mapper.py不应位于HDFS上,而应位于本地某处。然后,使用命令行中的-file <path_to_local_file>
选项将其发送到作业jar文件(doc):
/bin/hadoop jar contrib/streaming/hadoop-*streaming*.jar -mapper "python mapper.py" -file <path_to_your_local_mapper.py> -reducer "python reducer.py" -file <path_to_your_local_reducer.py> -input /home/hduser/VectMult3/in -output <output_dir_name>
答案 4 :(得分:0)
遇到了类似的问题,并发现确保以下行位于我的Python脚本的顶部,修复了它:
#!/usr/bin/python
也许给它一个去看看它是否有帮助?
P.S。另外,只要查看我们的Python映射器和缩减器,我们就会使用print语句而不在行尾添加注释。
答案 5 :(得分:0)
我遇到了同样的问题。 mapper.py 和 reducer.py 工作正常,但Hadoop流返回空文件,没有任何错误!
我通过使用Hadoop Streaming代码解决了这个问题,如下所示:(注意我用于-mapper和-reducer的格式!)
hadoop jar /usr/lib/hadoop-0.20-mapreduce/contrib/streaming/hadoop-*streaming*.jar -file /home/training/Desktop/mapper.py -mapper 'python mapper.py' -file /home/training/Desktop/reducer.py -reducer 'python reducer.py' -input /user/training/sales.csv -output /user/training/output18
我希望这有助于解决同样问题的其他人。