在Hadoop中链接多个MapReduce作业

在Hadoop中链接多个MapReduce作业,hadoop,mapreduce,Hadoop,Mapreduce,在应用MapReduce的许多实际情况中,最终的算法都是几个MapReduce步骤 i、 e.Map1、Reduce1、Map2、Reduce2等 因此,您可以将上一个reduce的输出作为下一个map的输入 一旦管道成功完成,您(通常)不希望保留中间数据。另外,由于中间数据通常是一些数据结构(如“映射”或“集合”),所以您不希望在写入和读取这些键值对方面花费太多精力 在Hadoop中,推荐的方法是什么 是否有一个(简单的)示例显示如何以正确的方式处理此中间数据,包括随后的清理?您可以使用ooz

在应用MapReduce的许多实际情况中,最终的算法都是几个MapReduce步骤

i、 e.Map1、Reduce1、Map2、Reduce2等

因此,您可以将上一个reduce的输出作为下一个map的输入

一旦管道成功完成,您(通常)不希望保留中间数据。另外,由于中间数据通常是一些数据结构(如“映射”或“集合”),所以您不希望在写入和读取这些键值对方面花费太多精力

在Hadoop中,推荐的方法是什么


是否有一个(简单的)示例显示如何以正确的方式处理此中间数据,包括随后的清理?

您可以使用oozie来barch处理MapReduce作业

我认为这篇关于雅虎开发者网络的教程将帮助您:

您可以使用
JobClient.runJob()
。第一个作业的数据输出路径将成为第二个作业的输入路径。需要使用适当的代码将这些参数作为参数传递给作业,以解析它们并设置作业的参数

但是,我认为上面的方法可能是现在较旧的mapredapi所采用的方法,但它仍然可以工作。在新的MapReduceAPI中会有类似的方法,但我不确定它是什么

至于在作业完成后删除中间数据,您可以在代码中执行此操作。我以前的做法是使用以下内容:

FileSystem.delete(Path f, boolean recursive);

其中路径是数据在HDFS上的位置。您需要确保只有在没有其他作业需要时才删除此数据。

实际上有很多方法可以做到这一点。我将集中讨论两个问题

一种方法是通过Riffle()一个注释库来识别依赖的事物,并按照依赖(拓扑)顺序“执行”它们

或者可以在Cascading()中使用Cascade(和MapReduceFlow)。未来的版本将支持Riffle注释,但它现在可以很好地与原始MR JobConf jobs配合使用

这方面的一个变体是根本不用手动管理MR作业,而是使用级联API开发应用程序。然后,通过级联规划器和流类在内部处理JobConf和作业链


通过这种方式,您可以将时间集中在您的问题上,而不是管理Hadoop作业等的机制上。您甚至可以在上面分层不同的语言(如clojure或jruby),以进一步简化您的开发和应用程序

有很多方法可以做到这一点

(1)级联作业

为第一个作业创建JobConf对象“job1”,并将所有参数设置为“input”作为inputdirectory,“temp”作为输出目录。执行此作业:

JobClient.run(job1).
在它的正下方,为第二个作业创建JobConf对象“job2”,并将所有参数设置为“temp”作为inputdirectory,“output”作为output directory。执行此作业:

JobClient.run(job2).
(2)创建两个JobConf对象,并像(1)一样设置其中的所有参数,只是不使用JobClient.run

然后使用jobconfs作为参数创建两个作业对象:

Job job1=新作业(jobconf1);
Job job2=新作业(jobconf2);
使用jobControl对象,可以指定作业依赖项,然后运行作业:

JobControl jbcntrl=新的JobControl(“jbcntrl”);
jbcntrl.addJob(job1);
jbcntrl.addJob(job2);
job2.addDependingJob(job1);
jbcntrl.run();

(3)如果您需要类似Map+| Reduce | Map*的结构,可以使用Hadoop 0.19版及更高版本附带的ChainMapper和ChainReducer类。

Apache Mahout项目中有一些将多个MapReduce作业链接在一起的示例。以下是其中一个例子:

RecommenderJob.java


尽管有复杂的基于服务器的Hadoop工作流引擎,例如oozie,但我有一个简单的java库,可以将多个Hadoop作业作为工作流执行。定义作业间依赖关系的作业配置和工作流在JSON文件中配置。一切都是外部可配置的,不需要对现有的map reduce实现进行任何更改即可成为工作流的一部分

详情可在此找到。github中提供了源代码和jar


Pranab

我认为oozie可以帮助后续作业直接从上一个作业接收输入。这样可以避免使用jobcontrol执行I/o操作

我们可以使用作业的
waitForCompletion(true)
方法来定义作业之间的依赖关系

在我的场景中,我有3份工作,它们相互依赖。在driver类中,我使用了下面的代码,它可以正常工作

publicstaticvoidmain(字符串[]args)引发异常{
//TODO自动生成的方法存根
CCJobExecution CCJobExecution=新的CCJobExecution();
Job distanceTimeFraudJob=ccJobExecution.configureDistanceTimeFraud(新配置(),参数[0],参数[1]);
Job spendingFraudJob=ccJobExecution.configureSpendingFraud(新配置(),参数[0],参数[1]);
Job locationFraudJob=ccJobExecution.configureLocationFraud(新配置(),参数[0],参数[1]);
System.out.println(“*************开始执行距离TimeFraudJob======================”);
距离timefraudjob.submit();
if(距离时间作业等待完成(真))
{
System.out.println(“===============================完成的距离TimeRaudJob===============================”);
System.out.println(“========================================已开始执行spendingFraudJob============================”);
spendingFraudJob.submit();
if(spendingFraudJob.waitForCompletion(真))
{
System.out.println(“================================================================================================================”);
系统。
JobControl jobControl = new JobControl(name);
<start to="mr-action1"/>
<action name="mr-action1">
   <!-- action for MRJob1-->
   <!-- set output path = /tmp/intermediate/mr1-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="mr-action2">
   <!-- action for MRJob2-->
   <!-- set input path = /tmp/intermediate/mr1-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="success">
        <!-- action for success-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="fail">
        <!-- action for fail-->
    <ok to="end"/>
    <error to="end"/>
</action>

<end name="end"/>
Configuration conf1 = new Configuration();
Job job1 = Job.getInstance(conf1, "a");

Configuration conf2 = new Configuration();
Job job2 = Job.getInstance(conf2, "b");
job1.waitForCompletion(true);