设为首页 收藏本站
查看: 726|回复: 0

[经验分享] 和远哥一起了解Hadoop的MapReduce是如何运行的

[复制链接]

尚未签到

发表于 2015-7-11 10:25:59 | 显示全部楼层 |阅读模式
Hadoop越来越火,而Hadoop里面有个核心的玩意,那就是MapReduce,它在Hadoop的并行计算中承担很重要的作用,也是在Hadoop下做程序开发时,必须要了解的,下面我们就MapRecude的一个简单例子WordCount来做一下深入的了解和分析。  
  先跟远哥一起先了解一下什么是MapReduce吧。
  

首先MapReduce它是两个英文单词组成的,Map表示映射,Reduce表示化简,它是一种编程模型,用于大规模数据集(大于1TB)的并行运算,主要思想来自函数式编程。  在Hadoop中,MapReduce过程分三个步骤:Map(主要是分解并行的任务)、Combine(主要是为了提高Reduce的效率)和Reduce(把处理后的结果再汇总起来) 。
  
  关于如何搭建Hadoop运行环境,可以阅读我的另外一篇博文:http://www.iyunv.com/taven/archive/2012/08/12/2634145.html

  好了,我们先看一下运行一个Hadoop作业的启动代码:
  


        Job job = new Job(conf, "word count");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(TokenizerMapper.class);
        job.setCombinerClass(IntSumReducer.class);
        job.setReducerClass(IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        
        System.exit(job.waitForCompletion(true) ? 0 : 1);  
  看到没,在运行一个Hadoop作业之前,先得指定 MapperClass 、CombinerClass 、ReducerClass .
  
  假设我们交给Hadoop去分析的一个文本内容为:


  lixy csy lixy zmde nitamade hehe

realy amoeba woyou weibo hehe  
  好了,提供的内容很简单,就是3行文本,第1行文本包含n个单词,第2行是空的,第3行也包含n个单词,单词与单词之间用空格隔开,下面我们来看看MapperClass 是如何实现的,又是如何运行的呢?看看 TokenizerMapper 的代码:
  


public class TokenizerMapper extends Mapper {

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public void map(Object key, Text value, Context context)    throws IOException, InterruptedException {
        
        System.out.println("TokenizerMapper.map...");
        System.out.println("Map key:"+key.toString()+" Map value:"+value.toString());
        
        StringTokenizer itr = new StringTokenizer(value.toString());
        
        while (itr.hasMoreTokens()) {
            String tmp = itr.nextToken();
            word.set(tmp);
            
            context.write(word, one);
            System.out.println("tmp:"+tmp+" one:"+one);
            
        }
        
        System.out.println("context:"+context.toString());

    }
}  注:这里远哥要说一下“IntWritable one = new IntWritable(1);”的用意,因为我们不管一个单词会出现几次,只要出现,我们就计算1次,所以“context.write(word, one)”这行代码将一个单词写入的时候,值永远是1;
  
  在运行的时候,根据你文件中内容的情况,上面的 map(Object key, Text value, Context context) 方法可能会被调用多次,将本例子提供的文件内容执行后,控制台输出内容如下(为了方便阅读,我添加了一些换行):
  


TokenizerMapper.map...
Map key:0 Map value:lixy csy lixy zmde nitamade hehe
tmp:lixy one:1
tmp:csy one:1
tmp:lixy one:1
tmp:zmde one:1
tmp:nitamade one:1
tmp:hehe one:1
context:org.apache.hadoop.mapreduce.Mapper$Context@1af0b4a3

TokenizerMapper.map...
Map key:34 Map value:
context:org.apache.hadoop.mapreduce.Mapper$Context@1af0b4a3

TokenizerMapper.map...
Map key:36 Map value:realy amoeba woyou weibo hehe
tmp:realy one:1
tmp:amoeba one:1
tmp:woyou one:1
tmp:weibo one:1
tmp:hehe one:1
context:org.apache.hadoop.mapreduce.Mapper$Context@1af0b4a3

IntSumReducer.reduce...
val.get():1
Reduce key:amoeba Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:csy Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
val.get():1
Reduce key:hehe Reduce result:2
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:2

IntSumReducer.reduce...
val.get():1
val.get():1
Reduce key:lixy Reduce result:2
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:2

IntSumReducer.reduce...
val.get():1
Reduce key:nitamade Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:realy Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:weibo Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:woyou Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:zmde Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@d5d4de6 Result:1  
   从TokenizerMapper的 map(Object key, Text value, Context context) 调用的信息输出情况可以分析出,文件内容中有两行,所以该方法一共调用了2次(因为TextInputFormat类型的,都是按行处理)。
  每一行的内容会在value参数中传进来,也就是说每一行的内容都对应了一个key,这个key为此行的开头位置在本文件中的所在位置(所以第1行的key是0,第2行的key是34,第3行的key是36),一般为数字的。
  在这个map方法中,我们可以加入一些自己的处理逻辑,比如根据空格来取得每个单词,然后我们需要将处理后的结果,写入到 context 参数中,便于hadoop处理完后续的处理逻辑。(这里我们需要注意的是“IntWritable one”变量都是数值1)
  
  上面看了map的过程,接下来我们再看reduce的过程,先看看 IntSumReducer 的代码:
  
  


public class IntSumReducer extends    Reducer {
   
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {

        System.out.println("IntSumReducer.reduce...");

        
        int sum = 0;
        for (IntWritable val : values) {
            sum += val.get();
            System.out.println("val.get():" + val.get());
        }

        result.set(sum);

        context.write(key, result);

        System.out.println("Reduce key:" + key.toString() + " Reduce result:"    + result.get());

        System.out.println("Reduce Context:" + context + " Result:" + result);

    }
}  
  执行调用后,控制台输出内容如下:
  

IntSumReducer.reduce...
val.get():1
Reduce key:amoeba Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:csy Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():2
Reduce key:hehe Reduce result:2
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:2

IntSumReducer.reduce...
val.get():2
Reduce key:lixy Reduce result:2
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:2

IntSumReducer.reduce...
val.get():1
Reduce key:nitamade Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:realy Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:weibo Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:woyou Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1

IntSumReducer.reduce...
val.get():1
Reduce key:zmde Reduce result:1
Reduce Context:org.apache.hadoop.mapreduce.Reducer$Context@6c04ab2f Result:1   
  通过执行 reduce(Text key, Iterable values, Context context) 方法,奇迹发生了,hadoop传到这里的参数,已经去重了。什么意思呢?就是说,参数key里面是单词名称,如果一个单词出现2次,那么参数values里面就会2个值,但是key只有1次。像“lixy”这个单词在第一行出现了2次,那么这里的key只出现1次,但是后面的values会有2个IntWritable,并且值都是1,这个为1的值其实就是你在map的时候,自己定的。
  
  这个例子只是简单的说明了MapReduce的一个简单使用,实际上他的功能远不只这些,还可以实现一些对数据库中数据的排序、统计等等,特别是对一些非常非常庞大的数据表。当你有一个1T的文本内容,需要统计里面每个单词分别出现多少次的时候,一台计算机去计算,会需要很长时间的,有可能光加载就要很长时间,但是如果你交给hadoop,并且配了几台机器一起跑的话,hadoop能把这1T的文本内容分成很多个小段,分发到不同的物理机器上,并行执行你的MapReduce逻辑,然后将几台物理机器上处理完成的内容汇总后给你,整个过程是分片、并行处理完成的,效率大大提高。
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-85453-1-1.html 上篇帖子: Spark集群搭建简配+它到底有多快?【单挑纯C/CPP/HADOOP】 下篇帖子: [hadoop源码阅读][9]-mapreduce-job提交过程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表