Hadoop的Word百分比程序

时间:2014-03-12 16:16:05

标签: java hadoop mapreduce word-count

我正在研究一个着名的WordCount程序的略微改进版本,该程序应该输出该单词所占的百分比。例如:

...
war 0.00002332423%
peace 0.0034234324%
...

基本上,我需要计算所有单词,计算每个单词的出现次数,将这组值除以总计数。所以应该至少有两个工作:

作业1

  • 获取input目录并生成两个输出目录:output1output2
  • 映射器:将对(word, 1)写入output1,将对("total_count", 1)写入output2
  • 缩减器:使用相同的键汇总对,在(word, n)中生成output1,计算("total_count", N)output2的总计数

作业2

  • output1output2作为输入文件夹,将结果写入output3
  • Mapper:什么都不做,只记下它得到的相同对
  • Reducer:获取单个值并将其除以total_count,将结果写入output3

我的问题:

  1. 我想避免两次原始输入,这就是为什么我要在Job1中计算字数和总数。但我不明白如何避免在一个输出中混淆结果。我曾尝试使用MultipleOutputs,但在这种情况下,映射器的结果不会进入reducer。

  2. Job2需要多个输入,而且需要首先阅读output2,因为没有总计数,从output1读取结果是没用的。我觉得这是使用MapReduce的错误方法(我们不应该使用任何类型的同步)但看不到正确的方法。

  3. Job2中的Mapper没有任何用处,只会浪费处理器时间。

2 个答案:

答案 0 :(得分:2)

只想到使用一份工作:

total_count可以从第一份工作的地图阶段计算出来。实际上,它已被计为MAP_OUTPUT_RECORDS。这是所有地图输出(key, value)对的总和。因此,如果您总是将1作为值,则此总和就是您想要的,即文档中的单词总数(重复)。

现在,我不知道你是否可以在减速器的配置中得到这个计数器。然后,您可以为每个单词输出(word, wordCount/MAP_OUTPUT_RECORDS)对。我想你可以通过以下方式做到这一点:

新API:

context.getCounter("org.apache.hadoop.mapred.Task$Counter", "MAP_OUTPUT_RECORDS").getValue();

旧API:

reporter.getCounter("org.apache.hadoop.mapred.Task$Counter", "MAP_OUTPUT_RECORDS").getValue();

答案 1 :(得分:0)

非优化方法是创建一个特殊单词(例如" 00000")并使用它来计算所有单词。 Mapper 1会为它遇到的每个单词写出(单词,1)和(" 00000",1)。然后,Reducer 1将计算所有单词以及计算总数(" 00000"的计数)。

下一个作业将有一个直通映射器,减速器将计算百分比。这里的诀窍是(1)有一个减速器和(2)选择你的" 00000"单词,以便它在所有其他单词之前排序。通过这种方式,总数首先传递给Reducer 2,并且对于所有后续的字数都是已知的。