学习hadoop,必不可少的就是写MapReduce程序,当然,对于简单的分析程序,我们只需一个MapReduce就能搞定,这里就不提单MapReuce的情况了,网上例子很多,大家可以百度Google一下。对于比较复杂的分析程序,我们可能需要多个Job或者多个Map或者Reduce进行分析计算。

多Job或者多MapReduce的编程形式有以下几种:

1、迭代式MapReduce

MapReduce迭代方式,通常是前一个MapReduce的输出作为下一个MapReduce的输入,最终可只保留最终结果,中间数据可以删除或保留,根据业务需要自己决定

示例代码如下:

  1. Configuration conf = new Configuration();
  2. //first Job
  3. Job job1 = new Job(conf,"job1");
  4. .....
  5. FileInputFormat.addInputPath(job1,InputPaht1);
  6. FileOutputFromat.setOutputPath(job1,Outpath1);
  7. job1.waitForCompletion(true);
  8. //second Mapreduce
  9. Job job2 = new Job(conf1,"job1");
  10. .....
  11. FileInputFormat.addInputPath(job2,Outpath1);
  12. FileOutputFromat.setOutputPath(job2,Outpath2);
  13. job2.waitForCompletion(true);
  14. //third Mapreduce
  15. Job job3 = new Job(conf1,"job1");
  16. .....
  17. FileInputFormat.addInputPath(job3,Outpath2);
  18. FileOutputFromat.setOutputPath(job3,Outpath3);
  19. job3.waitForCompletion(true);
  20. .....

下面列举一个mahout怎样运用mapreduce迭代的,下面的代码快就是mahout中kmeans的算法的代码,在main函数中用一个while循环来做mapreduce的迭代,其中:runIteration()是一次mapreduce的过程。

但个人感觉现在的mapreduce迭代设计不太满意的地方。

1. 每次迭代,如果所有Job(task)重复创建,代价将非常高。

2.每次迭代,数据都写入本地和读取本地,I/O和网络传输的代价比较大。

好像Twister和Haloop的模型能过比较好的解决这些问题,但他们抽象度不够高,支持的计算有限。

期待着下个版本hadoop更好的支持迭代算法。

  1. //main function
  2. while (!converged && iteration <= maxIterations) {
  3. log.info("K-Means Iteration {}", iteration);
  4. // point the output to a new directory per iteration
  5. Path clustersOut = new Path(output, AbstractCluster.CLUSTERS_DIR + iteration);
  6. converged = runIteration(conf, input, clustersIn, clustersOut, measure.getClass().getName(), delta);
  7. // now point the input to the old output directory
  8. clustersIn = clustersOut;
  9. iteration++;
  10. }
  11.  
  12. private static boolean runIteration(Configuration conf,
  13. Path input,
  14. Path clustersIn,
  15. Path clustersOut,
  16. String measureClass,
  17. String convergenceDelta)
  18. throws IOException, InterruptedException, ClassNotFoundException {
  19.  
  20. conf.set(KMeansConfigKeys.CLUSTER_PATH_KEY, clustersIn.toString());
  21. conf.set(KMeansConfigKeys.DISTANCE_MEASURE_KEY, measureClass);
  22. conf.set(KMeansConfigKeys.CLUSTER_CONVERGENCE_KEY, convergenceDelta);
  23.  
  24. Job job = new Job(conf, "KMeans Driver running runIteration over clustersIn: " + clustersIn);
  25. job.setMapOutputKeyClass(Text.class);
  26. job.setMapOutputValueClass(ClusterObservations.class);
  27. job.setOutputKeyClass(Text.class);
  28. job.setOutputValueClass(Cluster.class);
  29.  
  30. job.setInputFormatClass(SequenceFileInputFormat.class);
  31. job.setOutputFormatClass(SequenceFileOutputFormat.class);
  32. job.setMapperClass(KMeansMapper.class);
  33. job.setCombinerClass(KMeansCombiner.class);
  34. job.setReducerClass(KMeansReducer.class);
  35.  
  36. FileInputFormat.addInputPath(job, input);
  37. FileOutputFormat.setOutputPath(job, clustersOut);
  38.  
  39. job.setJarByClass(KMeansDriver.class);
  40. HadoopUtil.delete(conf, clustersOut);
  41. if (!job.waitForCompletion(true)) {
  42. throw new InterruptedException("K-Means Iteration failed processing " + clustersIn);
  43. }
  44. FileSystem fs = FileSystem.get(clustersOut.toUri(), conf);
  45.  
  46. return isConverged(clustersOut, conf, fs);
  47. }

2、依赖关系式MapReuce-JobControl

依赖关系式主要是由JobControl来实现,JobControl由两个类组成:Job和JobControl。其中,Job类封装了一个MapReduce作业及其对应的依赖关系,主要负责监控各个依赖作业的运行状态,以此更新自己的状态。

JobControl包含了一个线程用于周期性的监控和更新各个作业的运行状态,调度依赖作业运行完成的作业,提交处于READY状态的作业等,同事,还提供了一些API用于挂起、回复和暂停该线程。

示例代码如下:

  1. Configuration job1conf = new Configuration();
  2. Job job1 = new Job(job1conf,"Job1");
  3. .........//job1 其他设置
  4. Configuration job2conf = new Configuration();
  5. Job job2 = new Job(job2conf,"Job2");
  6. .........//job2 其他设置
  7. Configuration job3conf = new Configuration();
  8. Job job3 = new Job(job3conf,"Job3");
  9. .........//job3 其他设置
  10. job3.addDepending(job1);//设置job3和job1的依赖关系
  11. job3.addDepending(job2);
  12. JobControl JC = new JobControl("123");
  13. JC.addJob(job1);//把三个job加入到jobcontorl中
  14. JC.addJob(job2);
  15. JC.addJob(job3);
  16. JC.run();

3、线性链式MapReduce-ChainMapper/ChainReduce

ChainMapper/ChainReduce主要为了解决线性链式Mapper提出的。在Map或者Reduce阶段存在多个Mapper,这些Mapper像Linux管道一样,前一个Mapper的输出结果直接重定向到下一个Mapper的输入,行程流水线。

需要注意的是,对于任意一个MapReduce作业,Map和Reduce阶段可以有无线个Mapper,但是Reduce只能有一个。所以包含多个Reduce的作业,不能使用ChainMapper/ChainReduce来完成。

代码如下:

  1. ...
  2. conf.setJobName("chain");
  3. conf.setInputFormat(TextInputFormat.class);
  4. conf.setOutputFormat(TextOutputFormat.class);
  5.  
  6. JobConf mapper1Conf=new JobConf(false);
  7. JobConf mapper2Conf=new JobConf(false);
  8. JobConf redduce1Conf=new JobConf(false);
  9. JobConf mappe3Conf=new JobConf(false);
  10. ...
  11. ChainMapper.addMapper(conf,Mapper1.class,LongWritable.class,Text.class,Text.class,Text.class,true,mapper1Conf);
  12. ChainMapper.addMapper(conf,Mapper2.class,Text.class,Text.class,LongWritable.class,Text.class,false,mapper2Conf);
  13. ChainReducer.setReduce(conf,Reducer.class,LongWritable.class,Text.class,Text.class,Text.class,true,reduce1Conf);
  14. ChainReducer.addMapper(conf,Mapper3.class,Text.class,Text.class,LongWritable.class,Text.class,true,mapper3Conf);
  15. JobClient.runJob(conf);

4、子Job式MapReduce

子Job式其实也是迭代式中的一种,我这里单独的提取出来了,说白了,就是一个父Job包含多个子Job。

在nutch中,Crawler是一个父Job,通过run方法中调用runTool工具进行子Job的调用,而runTool是通过反射来调用子Job执行。

下面来看下Nutch里面是如何实现的

  1. ....
  2. private NutchTool currentTool = null;
  3. ....
  4. private Map<String, Object> runTool(Class<? extends NutchTool> toolClass,
  5. Map<String, Object> args) throws Exception {
  6. currentTool = (NutchTool) ReflectionUtils.newInstance(toolClass,
  7. getConf());
  8. return currentTool.run(args);
  9. }
  10. ...
  11. @Override
  12. public Map<String, Object> run(Map<String, Object> args) throws Exception {
  13. results.clear();
  14. status.clear();
  15. String crawlId = (String) args.get(Nutch.ARG_CRAWL);
  16. if (crawlId != null) {
  17. getConf().set(Nutch.CRAWL_ID_KEY, crawlId);
  18. }
  19. String seedDir = null;
  20. String seedList = (String) args.get(Nutch.ARG_SEEDLIST);
  21. if (seedList != null) { // takes precedence
  22. String[] seeds = seedList.split("\\s+");
  23. // create tmp. dir
  24. String tmpSeedDir = getConf().get("hadoop.tmp.dir") + "/seed-"
  25. + System.currentTimeMillis();
  26. FileSystem fs = FileSystem.get(getConf());
  27. Path p = new Path(tmpSeedDir);
  28. fs.mkdirs(p);
  29. Path seedOut = new Path(p, "urls");
  30. OutputStream os = fs.create(seedOut);
  31. for (String s : seeds) {
  32. os.write(s.getBytes());
  33. os.write('\n');
  34. }
  35. os.flush();
  36. os.close();
  37. cleanSeedDir = true;
  38. seedDir = tmpSeedDir;
  39. } else {
  40. seedDir = (String) args.get(Nutch.ARG_SEEDDIR);
  41. }
  42. Integer depth = (Integer) args.get(Nutch.ARG_DEPTH);
  43. if (depth == null)
  44. depth = 1;
  45. boolean parse = getConf().getBoolean(FetcherJob.PARSE_KEY, false);
  46. String solrUrl = (String) args.get(Nutch.ARG_SOLR);
  47. int onePhase = 3;
  48. if (!parse)
  49. onePhase++;
  50. float totalPhases = depth * onePhase;
  51. if (seedDir != null)
  52. totalPhases++;
  53. float phase = 0;
  54. Map<String, Object> jobRes = null;
  55. LinkedHashMap<String, Object> subTools = new LinkedHashMap<String, Object>();
  56. status.put(Nutch.STAT_JOBS, subTools);
  57. results.put(Nutch.STAT_JOBS, subTools);
  58. // inject phase
  59. if (seedDir != null) {
  60. status.put(Nutch.STAT_PHASE, "inject");
  61. jobRes = runTool(InjectorJob.class, args);
  62. if (jobRes != null) {
  63. subTools.put("inject", jobRes);
  64. }
  65. status.put(Nutch.STAT_PROGRESS, ++phase / totalPhases);
  66. if (cleanSeedDir && tmpSeedDir != null) {
  67. LOG.info(" - cleaning tmp seed list in " + tmpSeedDir);
  68. FileSystem.get(getConf()).delete(new Path(tmpSeedDir), true);
  69. }
  70. }
  71. if (shouldStop) {
  72. return results;
  73. }
  74. // run "depth" cycles
  75. for (int i = 0; i < depth; i++) {
  76.  
  77. status.put(Nutch.STAT_PHASE, "generate " + i);
  78. jobRes = runTool(GeneratorJob.class, args);
  79. if (jobRes != null) {
  80. subTools.put("generate " + i, jobRes);
  81. }
  82.  
  83. status.put(Nutch.STAT_PROGRESS, ++phase / totalPhases);
  84. if (shouldStop) {
  85. return results;
  86. }
  87. status.put(Nutch.STAT_PHASE, "fetch " + i);
  88. jobRes = runTool(FetcherJob.class, args);
  89. if (jobRes != null) {
  90. subTools.put("fetch " + i, jobRes);
  91. }
  92. status.put(Nutch.STAT_PROGRESS, ++phase / totalPhases);
  93. if (shouldStop) {
  94. return results;
  95. }
  96. if (!parse) {
  97. status.put(Nutch.STAT_PHASE, "parse " + i);
  98. jobRes = runTool(ParserJob.class, args);
  99. if (jobRes != null) {
  100. subTools.put("parse " + i, jobRes);
  101. }
  102. status.put(Nutch.STAT_PROGRESS, ++phase / totalPhases);
  103. if (shouldStop) {
  104. return results;
  105. }
  106. }
  107. status.put(Nutch.STAT_PHASE, "updatedb " + i);
  108. jobRes = runTool(DbUpdaterJob.class, args);
  109. if (jobRes != null) {
  110. subTools.put("updatedb " + i, jobRes);
  111. }
  112. status.put(Nutch.STAT_PROGRESS, ++phase / totalPhases);
  113. if (shouldStop) {
  114. return results;
  115. }
  116. }
  117. if (solrUrl != null) {
  118. status.put(Nutch.STAT_PHASE, "index");
  119. jobRes = runTool(SolrIndexerJob.class, args);
  120. if (jobRes != null) {
  121. subTools.put("index", jobRes);
  122. }
  123. }
  124. return results;
  125. }

MapReuce 编程总结-多MapReduce执行的更多相关文章

  1. Hadoop MapReduce执行过程详解(带hadoop例子)

    https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...

  2. 分析MapReduce执行过程

    分析MapReduce执行过程 MapReduce运行的时候,会通过Mapper运行的任务读取HDFS中的数据文件,然后调用自己的方法,处理数据,最后输出. Reducer任务会接收Mapper任务输 ...

  3. Hadoop学习之Mapreduce执行过程详解

    一.MapReduce执行过程 MapReduce运行时,首先通过Map读取HDFS中的数据,然后经过拆分,将每个文件中的每行数据分拆成键值对,最后输出作为Reduce的输入,大体执行流程如下图所示: ...

  4. .NET 并行(多核)编程系列之五 Task执行和异常处理

    原文:.NET 并行(多核)编程系列之五 Task执行和异常处理 .NET 并行(多核)编程系列之五 Task执行和异常处理 前言:本篇主要讲述等待task执行完成. 本篇的议题如下: 1. 等待Ta ...

  5. Hadoop MapReduce执行过程实例分析

    1.MapReduce是如何执行任务的?2.Mapper任务是怎样的一个过程?3.Reduce是如何执行任务的?4.键值对是如何编号的?5.实例,如何计算没见最高气温? 分析MapReduce执行过程 ...

  6. hadoop2.2编程:使用MapReduce编程实例(转)

    原文链接:http://www.cnblogs.com/xia520pi/archive/2012/06/04/2534533.html 从网上搜到的一篇hadoop的编程实例,对于初学者真是帮助太大 ...

  7. 大数据学习笔记——Hadoop编程实战之Mapreduce

    Hadoop编程实战——Mapreduce基本功能实现 此篇博客承接上一篇总结的HDFS编程实战,将会详细地对mapreduce的各种数据分析功能进行一个整理,由于实际工作中并不会过多地涉及原理,因此 ...

  8. 如何查看MapReduce执行的程序中的输出日志

    我们开发程序的时候,好多人都喜欢用sysout输出内容来查看运行情况.但是在MR程序里写了之后,却不知道去哪里查找,可以参考这篇文章. 第一种方法,我们可以在MapReduce任务查看页面找到这些日志 ...

  9. mapreduce执行流程

    角色描述:JobClient:执行任务的客户端JobTracker:任务调度器TaskTracker:任务跟踪器Task:具体的任务(Map OR Reduce) 从生命周期的角度来看,mapredu ...

随机推荐

  1. android入门——数据存储

    首先是SharedPreferences 用户偏好 package com.example.wkp.aboutdata; import android.content.Intent; import a ...

  2. Quartz 2D官方文档翻译(持续更新中)

    转换  核心绘图模型定义了两个完全独立的坐标空间:用户空间,一个是代表文档页,和设备空间,另外一个代表本机设备的分辨率.用户空间坐标是与设备空间中像素分辨率无关的浮点数字.当你想要打印或者显示你的文档 ...

  3. 20151211--EL表达式语言

  4. 如何用SQL操作数据------告别标题党

    额,首先跟大家道一个歉,由于本人上次利用标题来骗访问,对各位大哥大姐,叔叔阿姨,弟弟妹妹,and舅子老表的时间及流量造成了严重的浪费,本人深表歉意(好吧,其实本人内心还是有那么一丢丢的自豪的,毕竟是一 ...

  5. kafka 使用、介绍

    kafka  是一个消息系统, 具体资料可以参考官网: BrokerKafka集群包含一个或多个服务器,这种服务器被称为broker Topic每条发布到Kafka集群的消息都有一个类别,这个类别被称 ...

  6. poj2478--欧拉函数打表

    此题中对时间有要求,如直接使用欧拉函数求解,每输入一个n,就得进行循环求出<n的每个数的欧拉函数, 这样会超时, 于是我们可预先将欧拉函数打表, 再进行一个循环加法运算,便可不超时得解. #in ...

  7. 解读机器学习基础概念:VC维的来龙去脉 | 数盟

    http://dataunion.org/14581.html

  8. 解决Ubuntu DNS解析慢、上网速度慢

    自从ubuntu升级到10.04后,上网速度感觉变慢了很多(ADSL),原因也众说分云,有说是firefox浏览器造成的,于是用chrome访问,速度依然很慢,可见不是由于浏览器造成的. 网速慢, 是 ...

  9. Notes里OK,CANCEL按钮的设定

    message并不能达到想要的目的: If Not udoc Is Nothing Then        'MessageBox "既にデータがあります.先月のデータを削除してください.& ...

  10. Scala主构造器、私有构造器、构造器重载

    Scala中的主构造器跟在定义类的时候声明类名之后 如下: class scala(arg : String) { // } private[this] 修饰该字段只能被当前所对应的对象所访问,其他对 ...