在使用hadoop编写一个统计文件行数的程序的过程中,发现了一个十分奇怪的现象:
- mapper都达到99.99%了,但是状态还是RUNNING
- reducer一直是0%
- 登录到tasktracker上,top查看发现java进程一直占用99%的CPU
困惑了很久之后找到了原因,原来是reducer的代码书写的问题。
我的mapper函数是这样的:
public static class MapClass extends MapReduceBase
implements Mapper<LongWritable, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value,
OutputCollector<Text, IntWritable> output,
Reporter reporter) throws IOException {
output.collect(word, one);
}
}
reducer函数是:
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 += 1;
}
output.collect(key, new IntWritable(sum));
}
}
我的本意是,统计行数嘛,就是每行+1不就完了?
可是问题就出现在 sum += 1; 这一行上,改成
sum += values.next().get();
就可以了。
通过这个问题,我们可以进一步对hadoop的数据流处理机制有更加深入的思考。
reducer相对于mapper的关系就像consumer/producer的关系,如果reducer不consume掉mapper的输出,那么就会陷入死循环。。。
发现网上貌似没有人讨论过这个问题,记录于此供大家参考。
没有评论:
发表评论