我已经实现了一个简单的map reduce应用程序来检测最长的单词。作业成功执行。
但现在我想知道在减速机中使用局部变量来保持最大长度是否正确?因为在一个分布式环境中可能有多个缩减器,并且它们不共享该变量的值。
这是一个正确的假设吗?
在分布式环境中,当有独立的减速机时,输出将受到怎样的影响?
我使用一个定制的比较器,所以单词首先按长度排序,然后按值排序。每个mr阶段的输出如下所示:
Mapper Output:
ByeByeBye 9
HelloHelloHe222 15
HelloHelloHe222 15
HelloHelloHe333 15
HelloHelloHe333 15
HelloHelloHellw99999 20
Combiner Output:
ByeByeBye 9
HelloHelloHe222 15
HelloHelloHe333 15
HelloHelloHellw99999 20
ComparatorOutput:
HelloHelloHellw99999 20
HelloHelloHe222 15
HelloHelloHe333 15
ByeByeBye 9
Reducer Output:
HelloHelloHellw99999 20
减速器等级:
public class WordsReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private int maxLength = Integer.MIN_VALUE;
private IntWritable length = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
length = values.iterator().next();
if (length.get() >= maxLength){
maxLength = length.get();
context.write(key, length);
}
}
}
1条答案
按热度按时间i7uq4tfw1#
首先,我不认为有必要使用比较器,因为找到最大值不需要排序的数据集。
查找任何数据集的最大值是一个仅Map的操作。找到多个map任务的总体最大值需要减少这些单独的任务,而这只能由一个reducer来完成,在这个reducer中可以比较所有的数据。
减速机代码只输出每个减速机的最大值。你的关键是文本,但是有多个文本,所以它不可能看到最大值。您得到一个输出的原因是因为合并器已经将唯一的字符串收集到一个项中,并且这些项是按降序排序的。
您需要在Map器上只输出字符串的最大长度的逻辑,可能在对标记进行迭代时使用树Map来存储中间长度,而不是写入迭代的当前最大长度。使用字段也可以,但不是所有任务都共享。您可以使用counter对象,这些对象存储在context对象中。
如果您希望在当前代码中不使用组合器的情况下获得总体max,那么您可以在给定第一次运行的输出的输入的情况下运行它两次。想象一下这个场景,减速器1的最大长度为15,减速器2的最大长度为20。所以,你写了两个输出,而不仅仅是最大值。
如前所述,每个map任务都需要编写其各自的最大字符串。然后,实际上可以使用nullwriteable作为键,输出
null, "length,word"
. 在reducer中,获取所有值,提取长度,找到最大值,然后打印出来