3

考虑一个正在运行的作业,其中自定义 InputFormat 需要从其覆盖的方法Hadoop中与驱动程序类(即,与启动作业的类)通信(“返回”,类似于回调)一些简单的值,getSplits()使用新的mapreduceAPI(而不是mapred)。

理想情况下,这些值应该在内存中返回(而不是将它们保存到HDFSDistributedCache)。

如果这些值只是数字,人们可能会想使用Hadoop计数器。然而,在许多测试中,计数器似乎在该getSplits()阶段不可用,并且无论如何它们仅限于数字。

另一种方法是使用Configuration作业的对象,正如源代码所揭示的那样,它应该是内存中的同一个对象。getSplits()对于驱动程序类和驱动程序类,它应该是内存中的同一个对象。

在这种情况下,如果InputFormat想要向驱动程序类“返回”一个(比如说)正长值,代码将如下所示:

// In the custom InputFormat.
public List<InputSplit> getSplits(JobContext job) throws IOException
{
    ...
    long value = ... // A value >= 0
    job.getConfiguration().setLong("value", value);
    ...
}


// In the Hadoop driver class.
Job job = ... // Get the job to be launched
...
job.submit(); // Start running the job
... 
while (!job.isComplete())
{
    ...

    if (job.getConfiguration().getLong("value", -1))
    {
        ...
    }
    else
    {
        continue; // Wait for the value to be set by getSplits()
    }

    ...     
}

以上在测试中有效,但它是一种“安全”的价值交流方式吗?

或者对于这种内存中的“回调”有更好的方法吗?

更新

“内存回调”技术可能不适用于所有Hadoop发行版,因此,如上所述,一种更安全的方法是,与其保存要在Configuration对象中传回的值,不如创建一个自定义对象,将其序列化(例如,作为JSON),将其保存(在 HDFS 或分布式缓存中)并在驱动程序类中读取。我也测试了这种方法,它按预期工作。

4

1 回答 1

3

使用配置是一个非常合适的解决方案(诚然,对于我不确定我理解的问题),但是一旦作业实际提交到作业跟踪器,您将无法修改此值(客户端或任务端) 并期望在通信的另一侧看到更改(例如,在 map 任务中设置配置值不会持久保存到其他映射器,也不会保存到 reducer,也不会对作业跟踪器可见)。

因此,在您的示例中,将 getSplits 中的信息传回您的客户端轮询循环(以查看作业何时实际完成定义输入拆分)是可以的。

您使用它的更大目标或用例是什么?

于 2013-05-18T15:45:10.327 回答