不多说,直接上干货!

     Hadoop的MR作业支持链式处理,类似在一个生产牛奶的流水线上,每一个阶段都有特定的任务要处理,比如提供牛奶盒,装入牛奶,封盒,打印出厂日期,等等,通过这样进一步的分工,从而提高了生产效率,那么在我们的Hadoop的MapReduce中也是如此,支持链式的处理方式,这些Mapper像Linux管道一样,前一个Mapper的输出结果直接重定向到下一个Mapper的输入,形成一个流水线,而这一点与Lucene和Solr中的Filter机制是非常类似的,Hadoop项目源自Lucene,自然也借鉴了一些Lucene中的处理方式。

举个例子,比如处理文本中的一些禁用词,或者敏感词,等等,Hadoop里的链式操作,支持的形式类似正则Map+ Rrduce Map*,代表的意思是全局只能有一个唯一的Reduce,但是在Reduce的前后是可以存在无限多个Mapper来进行一些预处理或者善后工作的。

注意:

  1. 本人目前使用的版本是1.2.1,因此ChainMapper使用的还是old api。

  2. 老的API之中,只支持 N-Mapper + 1-Reducer的模式。 Reducer不在链式任务最开始即可。

比如:

  Map1 -> Map2 -> Reducer -> Map3 -> Map4

  (不确定在新版的API之中是否支持 N-Reducer的模式。不过new api 确实要简单简洁很多)

  在编程的时候,我们可以借用源码提供给我们的程序!在此基础上进行修改和编写。

比如我的源码本地目录如下:(找我的本地ChainMapper和ChainReducer案例

  D:\SoftWare\hadoop-2.2.0-src\hadoop-mapreduce-project\hadoop-mapreduce-client\hadoop-mapreduce-client-core\src\main\java\org\apache\hadoop\mapreduce\lib\chain

任务介绍:

  这个任务需要两步完成:

  1. 对一篇文章进行WordCount

  2. 统计出现次数超过5词的单词

WordCount我们很熟悉,因为版本限制,先使用old api 实现一次:

Java代码

  1. package hadoop_in_action_exersice;
  2. import java.io.IOException;
  3. import java.util.Iterator;
  4. import java.util.StringTokenizer;
  5. import org.apache.hadoop.fs.FileSystem;
  6. import org.apache.hadoop.fs.Path;
  7. import org.apache.hadoop.io.IntWritable;
  8. import org.apache.hadoop.io.LongWritable;
  9. import org.apache.hadoop.io.Text;
  10. import org.apache.hadoop.mapred.FileInputFormat;
  11. import org.apache.hadoop.mapred.FileOutputFormat;
  12. import org.apache.hadoop.mapred.JobClient;
  13. import org.apache.hadoop.mapred.JobConf;
  14. import org.apache.hadoop.mapred.MapReduceBase;
  15. import org.apache.hadoop.mapred.Mapper;
  16. import org.apache.hadoop.mapred.OutputCollector;
  17. import org.apache.hadoop.mapred.Reducer;
  18. import org.apache.hadoop.mapred.Reporter;
  19. import org.apache.hadoop.mapred.TextInputFormat;
  20. import org.apache.hadoop.mapred.TextOutputFormat;
  21. public class ChainedJobs {
  22. public static class TokenizeMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
  23. private final static IntWritable one = new IntWritable(1);
  24. public static final int LOW_LIMIT = 5;
  25. @Override
  26. public void map(LongWritable key, Text value,
  27. OutputCollector<Text, IntWritable> output, Reporter reporter)
  28. throws IOException {
  29. String line = value.toString();
  30. StringTokenizer st = new StringTokenizer(line);
  31. while(st.hasMoreTokens())
  32. output.collect(new Text(st.nextToken()), one);
  33. }
  34. }
  35. public static class TokenizeReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
  36. @Override
  37. public void reduce(Text key, Iterator<IntWritable> values,
  38. OutputCollector<Text, IntWritable> output, Reporter reporter)
  39. throws IOException {
  40. int sum = 0;
  41. while(values.hasNext()) {
  42. sum += values.next().get();
  43. }
  44. output.collect(key, new IntWritable(sum));
  45. }
  46. }
  47. public static void main(String[] args) throws IOException {
  48. JobConf conf = new JobConf(ChainedJobs.class);
  49. conf.setJobName("wordcount");           //设置一个用户定义的job名称
  50. conf.setOutputKeyClass(Text.class);    //为job的输出数据设置Key类
  51. conf.setOutputValueClass(IntWritable.class);   //为job输出设置value类
  52. conf.setMapperClass(TokenizeMapper.class);         //为job设置Mapper类
  53. conf.setCombinerClass(TokenizeReducer.class);      //为job设置Combiner类
  54. conf.setReducerClass(TokenizeReducer.class);        //为job设置Reduce类
  55. conf.setInputFormat(TextInputFormat.class);    //为map-reduce任务设置InputFormat实现类
  56. conf.setOutputFormat(TextOutputFormat.class);  //为map-reduce任务设置OutputFormat实现类
  57. // Remove output folder before run job(s)
  58. FileSystem fs=FileSystem.get(conf);
  59. String outputPath = "/home/hadoop/DataSet/Hadoop/WordCount-OUTPUT";
  60. Path op=new Path(outputPath);
  61. if (fs.exists(op)) {
  62. fs.delete(op, true);
  63. System.out.println("存在此输出路径,已删除!!!");
  64. }
  65. FileInputFormat.setInputPaths(conf, new Path("/home/hadoop/DataSet/Hadoop/WordCount"));
  66. FileOutputFormat.setOutputPath(conf, new Path(outputPath));
  67. JobClient.runJob(conf);         //运行一个job
  68. }
  69. }

上面是独立的一个Job,完成第一步。为了能紧接着完成第二步,我们需要在原来的基础上进行修改。

为了方便理解,上面的输入的例子如下:

Java代码

  1. accessed    3
  2. accessible  4
  3. accomplish  1
  4. accounting  7
  5. accurately  1
  6. acquire 1
  7. across  1
  8. actual  1
  9. actually    1
  10. add 3
  11. added   2
  12. addition    1
  13. additional  4

old api 的实现方式并不支持 setup() / cleanup() 操作这一点非常不好,因此在有可能的情况下最好还是要迁移到Hadoop 2.X

新的API会方便简洁很多

下面是增加了一个Mapper 来过滤

Java代码

  1. public static class RangeFilterMapper extends MapReduceBase implements Mapper<Text, IntWritable, Text, IntWritable> {
  2. @Override
  3. public void map(Text key, IntWritable value,
  4. OutputCollector<Text, IntWritable> output, Reporter reporter)
  5. throws IOException {
  6. if(value.get() >= LOW_LIMIT) {
  7. output.collect(key, value);
  8. }
  9. }
  10. }

这个Mapper做的事情很简单,就是针对每个key,如果他的value > LOW_LIMIT 那么就输出

所以,目前为止,任务链如下:

TokenizerMapper -> TokenizeReducer -> RangeFilterMapper

所以我们的main函数改成下面的样子:

Java代码

  1. public static void main(String[] args) throws IOException {
  2. JobConf conf = new JobConf(ChainedJobs.class);
  3. conf.setJobName("wordcount");           //设置一个用户定义的job名称
  4. //        conf.setOutputKeyClass(Text.class);    //为job的输出数据设置Key类
  5. //        conf.setOutputValueClass(IntWritable.class);   //为job输出设置value类
  6. //        conf.setMapperClass(TokenizeMapper.class);         //为job设置Mapper类
  7. //        conf.setCombinerClass(TokenizeReducer.class);      //为job设置Combiner类
  8. //        conf.setReducerClass(TokenizeReducer.class);        //为job设置Reduce类
  9. //        conf.setInputFormat(TextInputFormat.class);    //为map-reduce任务设置InputFormat实现类
  10. //        conf.setOutputFormat(TextOutputFormat.class);  //为map-reduce任务设置OutputFormat实现类
  11. // Step1 : mapper forr word count
  12. JobConf wordCountMapper  = new JobConf(false);
  13. ChainMapper.addMapper(conf,
  14. TokenizeMapper.class,
  15. LongWritable.class,     // input key type
  16. Text.class,             // input value type
  17. Text.class,             // output key type
  18. IntWritable.class,      // output value type
  19. false,                  //byValue or byRefference 传值还是传引用
  20. wordCountMapper);
  21. // Step2: reducer for word count
  22. JobConf wordCountReducer  = new JobConf(false);
  23. ChainReducer.setReducer(conf,
  24. TokenizeReducer.class,
  25. Text.class,
  26. IntWritable.class,
  27. Text.class,
  28. IntWritable.class,
  29. false,
  30. wordCountReducer);
  31. // Step3: mapper used as filter
  32. JobConf rangeFilterMapper  = new JobConf(false);
  33. ChainReducer.addMapper(conf,
  34. RangeFilterMapper.class,
  35. Text.class,
  36. IntWritable.class,
  37. Text.class,
  38. IntWritable.class,
  39. false,
  40. rangeFilterMapper);
  41. // Remove output folder before run job(s)
  42. FileSystem fs=FileSystem.get(conf);
  43. String outputPath = "/home/hadoop/DataSet/Hadoop/WordCount-OUTPUT";
  44. Path op=new Path(outputPath);
  45. if (fs.exists(op)) {
  46. fs.delete(op, true);
  47. System.out.println("存在此输出路径,已删除!!!");
  48. }
  49. FileInputFormat.setInputPaths(conf, new Path("/home/hadoop/DataSet/Hadoop/WordCount"));
  50. FileOutputFormat.setOutputPath(conf, new Path(outputPath));
  51. JobClient.runJob(conf);         //运行一个job
  52. }

下面是运行结果的一部分:

Java代码

  1. a   40
  2. and 26
  3. are 12
  4. as  6
  5. be  7
  6. been    8
  7. but 5
  8. by  5
  9. can 12
  10. change  5
  11. data    5
  12. files   7
  13. for 28
  14. from    5
  15. has 7
  16. have    8
  17. if  6
  18. in  27
  19. is  16
  20. it  13
  21. more    8
  22. not 5
  23. of  23
  24. on  5
  25. outputs 5
  26. see 6
  27. so  11
  28. that    11
  29. the 54

可以看到,英文之中,如果NLP不去除停用词(a, the, for ...) 等,效果确实会被大大的影响。

Hadoop的ChainMapper和ChainReducer使用案例(链式处理)(四)的更多相关文章

  1. Hadoop工作流--ChainMapper/ChainReducer?(三)

    不多说,直接上干货! Hadoop的ChainMapper和ChainReducer使用案例(链式处理) 什么是ChainMapper/ChainReducer?

  2. 组合式+迭代式+链式 MapReduce

    1.迭代式mapreduce 一些复杂的任务难以用一次mapreduce处理完成,需要多次mapreduce才能完成任务,例如Pagrank,Kmeans算法都需要多次的迭代,关于mapreduce迭 ...

  3. MR案例:链式ChainMapper

    类似于Linux管道重定向机制,前一个Map的输出直接作为下一个Map的输入,形成一个流水线.设想这样一个场景:在Map阶段,数据经过mapper01和mapper02处理:在Reduce阶段,数据经 ...

  4. Hadoop基础-Map端链式编程之MapReduce统计TopN示例

    Hadoop基础-Map端链式编程之MapReduce统计TopN示例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.项目需求 对“temp.txt”中的数据进行分析,统计出各 ...

  5. Hadoop生态圈-Knox网关的应用案例

    Hadoop生态圈-Knox网关的应用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Knox网关简介 据Knox官网所述(http://knox.apache.org/) ...

  6. Apache Hadoop 2.9.2 的归档案例剖析

    Apache Hadoop 2.9.2 的归档案例剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   能看到这篇文章说明你对NameNode 工作原理是有深入的理解啦!我们知道 ...

  7. Hadoop生态圈-CDH与HUE使用案例

    Hadoop生态圈-CDH与HUE使用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HUE的介绍 1>.HUE的由来 HUE全称是HadoopUser Experi ...

  8. hadoop一代集群运行代码案例

    hadoop一代集群运行代码案例 集群 一个 master,两个slave,IP分别是192.168.1.2.192.168.1.3.192.168.1.4               hadoop版 ...

  9. Hadoop基础-MapReduce的Partitioner用法案例

    Hadoop基础-MapReduce的Partitioner用法案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Partitioner关键代码剖析 1>.返回的分区号 ...

随机推荐

  1. UICollectionView基础用法

    初始化部分: UICollectionViewFlowLayout *flowLayout= [[UICollectionViewFlowLayout alloc]init]; self.myColl ...

  2. spring boot 打印sql

    配置: logging.level.gov.chinatax.ctims.dao.mapper=DEBUG or logging: level: gov.chinatax.ctims.dao.mapp ...

  3. Eclipse 创建新的workspace

    工具:eclipse  版本:4.5.1 1.配置jdk(java-Compiler).maven(Mven-User Settings) 2.从svn拉取项目,创建.project(修改其项目名称) ...

  4. YTU 1055: 输入字符串以及输出

    1055: 输入字符串以及输出 时间限制: 1 Sec  内存限制: 128 MB 提交: 694  解决: 476 题目描述 编写一函数,由实参传来一个字符串,统计此字符串中字母.数字.空格和其它字 ...

  5. 通过ODC方法改善软件测试:3个案例研究

    正交缺陷分类法(ODC)是一种用于分析软件缺陷的归类方法.它可以结合软件开发过程的一系列数据分析技术,为测试组织提供了一个强大的针对开发过程和软件产品的评估方法.在本篇文章中,会列举三个案例研究来说明 ...

  6. vmware9虚拟机通过NAT上网方式设置

    vmware虚机上网的网络连接方式有bridge.NAT.Host-only等,如果对这个不了解的可以学习这篇文章http://wangchunhai.blog.51cto.com/225186/38 ...

  7. linux编程 fmemopen函数打开一个内存流 使用FILE指针进行读写访问

    fmemopen()函数打开一个内存流,使你可以读取或写入由buf指定的缓冲区.其返回FILE*fp就是打开的内存流,虽然仍使用FILE指针进行访问,但其实并没有底层文件(并没有磁盘上的实际文件,因为 ...

  8. codeforces 690C3 C3. Brain Network (hard)(lca)

    题目链接: C3. Brain Network (hard) time limit per test 2 seconds memory limit per test 256 megabytes inp ...

  9. 移动前端开发之viewport的理解

    在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或 ...

  10. [USACO2006 DEC] Wormholes

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1715 [算法] 用SPFA判定负环是否存在即可 时间复杂度 : O(N ^ 2) [ ...