Ruby中一个简单的wordcount reducer就像这样:
#!/usr/bin/env ruby
wordcount = Hash.new
STDIN.each_line do |line|
keyval = line.split("|")
wordcount[keyval[0]] = wordcount[keyval[0]].to_i+keyval[1].to_i
end
wordcount.each_pair do |word,count|
puts "#{word}|#{count}"
end
它在STDIN中获取所有映射器的中间值。不是来自特定的钥匙。 所以实际上只有一个减速器(而不是每个单词或每组单词的减速器)。
但是,在Java示例中,我看到这个接口获取了一个键和值列表inout。这意味着在缩减和缩减器可以并行运行之前,按键对中间映射值进行分组:
public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
int sum = 0;
while (values.hasNext()) {
sum += values.next().get();
}
output.collect(key, new IntWritable(sum));
}
}
这是仅限Java的功能吗?或者我可以使用Ruby来使用Hadoop Streaming吗?
答案 0 :(得分:5)
Reducers将始终并行运行,无论您是否使用流式传输(如果您没有看到这一点,请验证作业配置是否设置为允许多个reduce任务 - 请参阅群集中的mapred.reduce.tasks或工作配置)。不同之处在于,当您使用Java与流式传输时,框架会为您提供更好的解决方案。
对于Java,reduce任务获取特定键的所有值的迭代器。如果您在reduce任务中对地图输出求和,则可以轻松地遍历值。在流式传输中,您实际上只获得了一对键值对。您 保证按键排序值,并且对于给定键的值不会在reduce任务中拆分,但您需要的任何状态跟踪由您决定。例如,在Java中,您的地图输出以符号形式以
的形式出现在您的reducer中key1,{val1,val2,val3} key2,{val7,val8}
使用流媒体,您的输出看起来像
key1,val1 key1,val2 key1,val3 key2,val7 key2,val8
例如,要编写计算每个键值的总和的reducer,您需要一个变量来存储您看到的最后一个键以及一个用于存储总和的变量。每次读取新的键值对时,都会执行以下操作:
HTH。
答案 1 :(得分:1)
我自己没有尝试过Hadoop Streaming,但是从阅读文档中我认为你可以实现类似的并行行为。
不是将具有关联值的键传递给每个reducer,而是将按键对映射器输出进行分组。它还保证具有相同键的值不会被分割为多个reducer。这与普通的Hadoop功能略有不同,但即便如此,还原工作将分布在多个Reducer上。
尝试使用-verbose
选项获取有关实际情况的更多信息。您还可以尝试使用-D mapred.reduce.tasks=X
选项进行试验,其中X是所需的缩减器数量。