Hadoop数据和控制流程

时间:2012-11-17 14:31:41

标签: hadoop mapreduce control-flow dataflow

我正在编写一个Hadoop应用程序,但似乎我误解了hadoop究竟是如何工作的。我的输入文件是地图的图块,根据QuadTile原则命名。我需要对它们进行子采样,并将它们拼接在一起,直到我有一个更高级别的区块,覆盖更大的区域,但分辨率更低。就像在谷歌地图中缩小一样。

我做过的一件事就是我编写了一个映射器,它在每个(不可分割的)磁贴上执行,如下所示:

public void map(Text keyT, ImageWritable value, Context context) throws IOException, InterruptedException {

     String key = keyT.toString();

    //check whether file needs to be processed
     if(key.startsWith(context.getJobName(), 0)){

         String newKey = key.substring(0, key.length()-1);
         ImageWritable iw = subSample(value);
         char region = key.charAt(key.length()-1);
         iw.setRegion(region);
         context.write(new Text(newKey), iw);
     }else{
         //tile not needed in calculation
     }
 }

我的减速机看起来像这样:

public void reduce(Text key, Iterable<ImageWritable> values, Context context) throws IOException, InterruptedException{

    ImageWritable higherLevelTile = new ImageWritable();
    int i = 0;
    for(ImageWritable s : values){
        int width = s.getWidth();
        int height = s.getHeight();
        char c = Character.toUpperCase(s.getRegion());
        int basex=0, basey=0;
        if(c=='A'){
            basex = basey = 0;
        }else if(c=='B'){
            basex = width;
            basey = 0;
        }else if(c=='C'){
            basex = 0;
            basey = height;             
        }else{
            basex = width;
            basey = height;
        }

        BufferedImage toDraw = s.getBufferedImage();
        Graphics g = higherLevelTile.getBufferedImage().getGraphics();
        g.drawImage(toDraw, basex, basey, null);
    }               
    context.write(key, higherLevelTile);

}

正如您可能从我的代码派生出来的那样,我希望hadoop能够以下列方式执行: 1)映射第一级的所有图块 2)先做减少。在这里我期望Iterable值有四个元素:较低级别的四个子样本瓦片。 3)当前在上下文中映射al tile 4)减少上下文中的所有图块。同样,Iterable值将有4个元素...... 5)......重复...... 6)当没有剩余地图时 - &gt;写输出

事实证明,这是不正确的。我的reducer在每个Map之后调用,Iterable似乎永远不会有多个元素。我试图通过假设Iterable有2个元素来改变reducer代码来解决这个问题:一个子采样值,一个部分完成更高级别的tile。事实证明,这也不正确。

任何人都可以告诉我,或指向我,实际上hadoop的流量是多少?我该怎么做才能让我的用例工作?我希望我能清楚地解释清楚。

1 个答案:

答案 0 :(得分:3)

您的假设是正确的,所有地图在第一次减少开始之前就已完成。这是因为每个reduce都保证按排序顺序获取其输入,而最后一个完成的map可能会产生所有减少的第一个键。

每个地图都会产生输出,一个名为分区器的可插拔接口会选择应该接收每个键的reduce。默认使用key.hashCode() % num_reduces,因为在正常情况下可以提供良好的分布。这可能是您的问题,因为没有要求"A""AB""ABC"将会进行相同的缩减。

最后,为每个键调用每个reduce。迭代器遍历与同一个键关联的值。请注意,值通常未排序,但可以使用辅助排序控制。

看看:http://riccomini.name/posts/hadoop/2009-11-13-sort-reducer-input-value-hadoop/

如果你想要一个二级排序的例子,我写了一个并把它放在Hadoop的例子中。 http://svn.apache.org/repos/asf/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-examples/src/main/java/org/apache/hadoop/examples/SecondarySort.java