mapper,reducer实例变量值的恢复

上一篇 / 下一篇  2013-08-02 15:27:44 / 个人分类:分布式技术学习

 

代码示例:

public static class TestMapper extends Mapper{
  private  String isOut ="out" ;//错误处
   protected void map(LongWritable key, Text value, Context context)
   throws IOException, InterruptedException {
        String line=value.toString();
        String tmp[]=line.split( ";",-1);
         if (tmp.length !=2){
               isOut="in" ;
        }
         if(isOut .equals("out")){
              context.write( new Text(key.toString()), new Text(context.toString()));
        }
        }

}

现象及后果:

所有被分到一个map里的record,一旦出现以“;”为分割符,长度不为2的,那么后面的record都不会被输出了。

原因分析:

这个错误跟mapreduce的计算机制有关,TestMapper继承了Mapper之后,整个类的实例变量只在启动的时候初始化一次,也就是说 private String isOut="out"这句话只会在最开始执行一次。map函数里面的则是每次都执行(局部变量每次都重新算)。也就是说一旦出现一条数据走到了 inOut="in"。那么这个变量直到结束都是in,除非后面还有逻辑会去修改isOut的值。 那么如果map里面用到了实例变量并且会去修改它那么record之间就是可以相互干扰的。

建议:

对于这种实例变量,如果在map函数中要根据计算结果进行修改,而对于每一条记录又希望这个值是独立的,不受其他record计算影响的,那么首先在map函数刚开始给他一个初始值,或者clear掉原来的数值。 reduce也是同理的。

public static class TestMapper extends Mapper{
   protected void map(LongWritable key, Text value, Context context)
   throws IOException, InterruptedException {
    String isOut ="out" ;//修改处
        String line=value.toString();
        String tmp[]=line.split( ";",-1);
         if (tmp.length !=2){
               isOut="in" ;
        }
         if(isOut .equals("out")){
              context.write( new Text(key.toString()), new Text(context.toString()));
        }
        }

}

危险系数:5颗地雷。 因为这种bug的现象就是有的record计算结果是对的,有的是错的,而在进行测试验证的时候也很有可能拿到的都是计算正确的。


TAG:

 

评分:0

我来说两句

Open Toolbar