2

我正在编写一个 Hadoop 应用程序以特定分辨率计算地图数据。我的输入文件是地图的瓦片,根据QuadTile原则命名。我需要对它们进行二次采样,并将它们拼接在一起,直到我有一个覆盖更大区域但分辨率更低的某个更高级别的图块。就像缩小谷歌地图一样。

目前,我的 Mapper 对瓦片进行子采样,而我的化简器将瓦片组合到某个级别并形成上一层的瓦片。所以太好了。但是根据我需要的图块,我需要重复这些地图并减少步骤 ax 次,这是迄今为止我无法做到的。

最好的方法是什么?是否可以不明确地将切片保存在某个临时目录中并在这些临时目录上启动一个新的 mapreduce 作业,直到我得到我想要的?我认为完美的解决方案大致类似于'while(context.hasMoreThanOneKey()){iterate mapreduce}'。

在回答之后,我现在编写了一个扩展 Job 的类 TileJob。但是,mapreduce 仍然没有被链接。你能告诉我我做错了什么吗?

public boolean waitForCompletion(boolean verbose) throws IOException, InterruptedException, ClassNotFoundException{

    if(desiredkeylength != currentinputkeylength-1){            
        System.out.println("In loop, setting input at " + tempout);
        String tempin = tempout;
        FileInputFormat.setInputPaths(this, tempin);            
        tempout = (output + currentinputkeylength + "/");
        FileOutputFormat.setOutputPath(this, new Path(tempout));
        System.out.println("Setting output at " + tempout);
        currentinputkeylength--;
        Configuration conf = new Configuration();
        TileJob job = new TileJob(conf);
        job.setJobName(getJobName());
        job.setUpJob(tempin, tempout, tiletogenerate, currentinputkeylength);       
         return job.waitForCompletion(verbose);

    }else{
        //desiredkeylength == currentkeylength-1
        System.out.println("In else, setting input at " + tempout);

        String tempin = tempout;
        FileInputFormat.setInputPaths(this, tempin);            
        tempout = output;
        FileOutputFormat.setOutputPath(this, new Path(tempout));
        System.out.println("Setting output at " + tempout);
        currentinputkeylength--;
        Configuration conf = new Configuration();
        TileJob job = new TileJob(conf);
        job.setJobName(getJobName());
        job.setUpJob(tempin, tempout, tiletogenerate, currentinputkeylength);
        currentinputkeylength--;

        return super.waitForCompletion(verbose);
    }   

}
4

1 回答 1

1

通常,您通过一个驱动程序类的主要方法来配置作业、配置和格式类型(输入和输出)来启动 mapreduce 步骤。一旦一切准备就绪,主方法调用 Job::waitForCompletion() 提交作业并等待作业完成后再继续。

您可以将其中一些逻辑包装在一个循环中,该循环重复调用 Job::waitForCompletion() 直到满足您的条件。您可以使用计数器来实施您的标准。将逻辑放入您的 reduce() 方法中,以使用键的数量设置或增加计数器。驱动程序类中的循环可以从 Job 实例中获取该(分布式)计数器的值,然后使用该值编写 while 表达式。

您使用的文件位置取决于您。在此驱动程序循环中,您可以更改输入和输出的文件位置,或保持相同。

我可能应该补充一点,您应该继续在循环内创建一个新的 Job 和 Configuration 实例。我不知道这些对象在这种情况下是否可重用。

public static void main(String[] args) {
    int keys = 2;
    boolean completed = true;
    while (completed & (keys > 1)) {

        Job job = new Job();

            // Do all your job configuration here

        completed = job.waitForCompletion();
        if (completed) {
            keys = job.getCounter().findCounter("Total","Keys").getValue();
        }
    }

}
于 2012-11-18T14:37:46.387 回答