【问题标题】:map reduce with two input files, with one file processed based on anothermap reduce 带有两个输入文件,一个文件基于另一个文件处理
【发布时间】:2017-07-21 23:32:33
【问题描述】:

我需要编写一个将输入作为两个输入文件的 map reduce。 第一个输入文件如下所示:

key1 , 25
key1 , 35
key1 , 60
key2 , 30
key3 , 45
key3 , 65

第二个输入文件如下:

key1, -10
key2, -20
key3, -15

我需要得到一个输出:

key1 , 15
key1 , 25
key1 , 50
key2 , 10
key3 , 30
key3 , 50

(输出是第一个输入文件的值减去第二个输入文件的值)

如何做到这一点? mapper 和 reducer 任务会是什么样子?

我的做法如下:

我想我必须有两个映射器,每个输入文件一个(可以使用一个映射器来读取两个文件吗?)。映射器将简单地发出键和值。

在 reducer 端,当我收到与某个键对应的所有值时,我必须将来自第一个文件的值减去第二个文件中的值。

所以我需要找出对应的值是来自第二个输入文件还是第一个文件。这是怎么做到的?

还有其他更好的方法吗?

【问题讨论】:

  • 一个map,如果key不存在就创建map entry,否则从已有的map entry中加减key值

标签: java hadoop mapreduce hadoop-partitioning


【解决方案1】:

读入一个单独的映射器,并更改内容,以便您知道它们来自哪个文件。例如输出

key1 , 25 , file1
key1 , 35 , file1
key1 , 60 , file1
key2 , 30 , file1
key3 , 45 , file1
key3 , 65 , file1

key1, -10 , file2
key2, -20 , file2
key3, -15 , file2

然后,您可以通过单个 mapreduce 阶段一起输出两个输出,您将知道哪个来自哪里,并且您可以在您的 reducer 中相应地操作您的数据。

【讨论】:

    【解决方案2】:

    这可以在单个 MapReduce 程序中完成。您可以使用 MapReduce 框架的 MultipleInputs 支持。

    • 为每个输入文件定义两个映射器类。然后输出key、value为key#fileName、value对。
    • 定义一个自定义分区器,它只考虑实际键并忽略附加的文件名来对数据进行分区。这样两个文件中的相同键就会进入同一个 reducer。
    • reducer 将从 file1 中获取 key 的值列表。将此值列表保存在内存中,并从 file2 中获取相同键的值列表。这两个将连续出现,因为我们仅对关键部分的数据进行了分区,并且比较器也会根据关键值对它们进行排序。假设第一个文件名按字母顺序排列。然后使用第二个文件值对第一个文件值列表执行所需的操作。

      Configuration conf = new Configuration();
      Job job = new Job(conf, "aggprog");        
      
      MultipleInputs.addInputPath(job,new Path(args[0]),TextInputFormat.class,MapperOne.class);
      MultipleInputs.addInputPath(job,new Path(args[1]),TextInputFormat.class,MapperTwo.class);
      
      conf.setPartitionerClass(CustomPartitioner.class);
      

      希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 2015-01-24
      • 2018-03-18
      相关资源
      最近更新 更多