Hadoop 数据和控制流

标签 hadoop mapreduce control-flow dataflow

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

我所做的其中一件事是我编写了一个映射器,它在每个(不可拆分的)图 block 上执行,如下所示:

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
     }
 }

我的 reducer 是这样的:

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 值具有四个元素:较低级别的四个二次采样图 block 。 3) 映射当前在上下文中的所有图 block 4)减少上下文中的所有图 block 。同样,可迭代值将有 4 个元素...... 5) ... 重复... 6) 当没有更多 map 剩余时 -> 写入输出

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

谁能告诉我,或指出我 hadoop 的实际流程如何?我应该怎么做才能使我的用例正常工作?我希望我解释清楚了。

最佳答案

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

每个映射产生它的输出,一个称为分区器的可插入接口(interface)选择应该接收每个键的缩减。默认使用 key.hashCode() % num_reduces,因为这在正常情况下提供了良好的分布。这可能是您的问题,因为没有要求 "A""AB""ABC" 将转到相同的 reduce。

最后,每个 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

关于Hadoop 数据和控制流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13431520/

相关文章:

sql - Teradata 转换为 hive sql

hadoop - sudo hadoop 与 su hadoop

hadoop - Apriori 和关联规则与 Hadoop

hadoop - 提高 Java MapReduce 性能的思路

javascript - 通过 JavaScript 中的事件控制流程代码

控制流程理解

linux - 在 OpenStack 中安装 Sahara

hadoop - 使用Multiple Outputs Mapreduce将数据写入多个文件

java - 烟灰、身份 stmts 和异常处理期间的控制流

java - Apache Flume/var/log/flume-ng/flume.log(权限被拒绝)