Python MapReduce Hadoop Streaming Job需要多个输入文件?

时间:2013-12-27 10:20:27

标签: python hadoop mapreduce hadoop-streaming

我的群集File AFile B中有两个文件,包含以下数据 -

档案A

#Format: 
#Food Item | Is_A_Fruit (BOOL)

Orange | Yes
Pineapple | Yes
Cucumber | No
Carrot | No
Mango | Yes

档案B

#Format:
#Food Item | Vendor Name

Orange | Vendor A
Pineapple | Vendor B
Cucumber | Vendor B
Carrot | Vendor B
Mango | Vendor A

基本上我想找出答案 每个供应商销售多少水果?

预期产出:

Vendor A | 2
Vendor B | 1

我需要使用hadoop流式传输python map reduce。

我已经阅读了如何进行基本字数统计,我从sys.stdin读取并为减速器发出k,v对然后减少。

如何处理此问题?

我主要关心的是如何从多个文件中读取,然后在Hadoop Streaming中进行比较。

我可以在普通的python中做到这一点(即没有MapReduce& Hadoop,它很简单。)但是对于我拥有的庞大数据大小是不可行的。

4 个答案:

答案 0 :(得分:6)

文件A真的那么大吗?我会把它放在DistributedCache中并从那里读取它。要将其放入分布式缓存中,请在Hadoop流式调用中使用此选项:

-cacheFile 'hdfs://namenode:port/the/hdfs/path/to/FileA#FileA'

(我认为以下内容也应该有效,但我没有尝试过:)

-cacheFile '/the/hdfs/path/to/FileA#FileA'

请注意,#fileA是您用来使映射器可以使用该文件的名称。

然后,在您的映射器中,您将从sys.stdin读取FileB(假设您使用-input '/user/foo/FileB'调用Hadoop Streaming)并且,要读取FileA,您应该执行以下操作:

f = open('FileA', 'r')
...
f.readline()

现在,我想你已经想到了这一点,但对我来说,有一个这样的映射器是有道理的:

  1. 打开FileA
  2. 逐行读取FileA(在循环中)并将其加载到地图中,以便您可以轻松查找密钥并找到其值(是,否)。
  3. 从stdin读取主循环。在循环中,对于每一行(在FileB中),检查你的地图(见第2步),看看你是否有水果......等。

答案 1 :(得分:4)

请查看this示例,因为它与您正在寻找的内容非常直接相关。

答案 2 :(得分:1)

一种方法是将此作为两个工作。

  1. 过滤FileB,以便仅保留包含水果的行
    • Map1:“食物项目”的复合键,以及数据来自哪个文件。对“食品项目”进行分区,并对该行是否包含“Is_A_Fruit”信息进行二次排序(以确保每个食品的减速器首先读取该信息)。
    • Reduce1:使用二级排序,排序数据中的第一行将指示此Food Item是否为水果(在这种情况下reducer将输出它)或不是(在这种情况下它不会)。
  2. 使用供应商作为密钥来计算每个供应商的水果数量。
    • 此处第一个作业的MapReduce输出现在与FileB具有相同的结构,但所有行都是Fruits,所以这更像是wordcount,以Vendor Name作为键,然后计算行数。
    • 如果您想要独特的水果,您可能需要再次使用二级排序,以消除将与每个供应商相关的所有水果加载到内存中的需要。
  3. 这就是说:@cabad建议的解决方案最好是文件足够小。

    如果没有,那么二次分类的方法是最好的。看一下@ Simplefish的答案this tutorial中建议的here,了解如何在分区内进行二级排序(这些关键字将指向正确的方向来做你想做的事情:做出保证与传递给reducer的给定键关联的数据的顺序。)

    最后一点说明:您的问题不是“如何从多个文件中读取”,因为您设计的任何解决方案都不能依赖于知道输入来自哪个文件(您需要依赖于数据的结构) ,虽然这不是本例中的问题)。

答案 3 :(得分:1)

您只会将包含文件的目录提供给hadoop。 Hadoop框架将读取它们。你没有。

Hadoop会将您编码的地图类应用于所有文件内容。

然后,hadoop会将减少你编码的类应用于地图类的所有输出。