研究MapReduce已经有一段时间了。起初是从分析WordCount程序开始,后来开始阅读Hadoop源码,自认为已经看清MapReduce的运行流程。现在把自己的理解贴出来,与大家分享,欢迎纠错。

还是以最经典的WordCount程序作为基础,来分析map阶段、reduce阶段和最复杂的shuffle阶段。

文本1:hello world                                      文本2:map reduce

hello hadoop                                              java interface

abc qaz                                                      java hdfs

     java jvm                                                    spark storm

这样的2个小文本文件(不足64M),肯定会产生2个map任务,reduce任务默认是1个。当然,map任务和reduce任务的个数都可以在程序中或者配置文件中人为设置。为了说明partition的过程,我们把reduce任务的个数设为2。

1、map阶段

map1                                                            map2

输入:<xxxx, hello world>                                           <xxxx, map reduce>

<xxxx, hello hadoop>                                        <xxxx, java interface>

    <xxxx, abc qaz>                                               <xxxx, java hdfs>

    <xxxx, java jvm>                                              <xxxx, spark storm>

切分:<hello, 1>                                                           <map, 1>

<word, 1>                                                           <reduce, 1>

   <hello, 1>                                                           <java, 1>

   <hadoop, 1>                                                       <interface, 1>

   <abc, 1>                                                             <java, 1>

   <qaz, 1>                                                             <hdfs, 1>

   <java, 1>                                                            <spark, 1>

   <jvm, 1>                                                             <storm, 1>

2、shuffle阶段

切分完毕后,每一组<key, value>都会不断地被collect到一个内存缓冲区中,对应代码中的数据结构MapOutputBuffer。

partition过程:每一组<key, value>在被收集的时候,就已经确定了分区(partition),即在这个时候就已经确定了要交给哪个reduce任务处理。分区会给<key, value>加上一个索引标识。假设分区后(分区算法可以设定,默认是hash值模运算),数据如下:reduce1的标识是0,reduce2的标识是1

<hello, 1>                0                                          <map, 1>                         0

<word, 1>                1                                          <reduce, 1>                      1

                                              <hello, 1>                0                                          <java, 1>                          0

                                              <hadoop, 1>             1                                          <interface, 1>                   1

                                              <abc, 1>                  0                                           <java, 1>                         0

                                              <qaz, 1>                  1                                           <hdfs, 1>                         1

                                              <java, 1>                 0                                           <spark, 1>                        0

                                              <jvm, 1>                  1                                           <storm, 1>                       1

spill过程:缓冲区默认是100M,每当里面的数据达到80M(比例80%,这个比例也可以人为设置),就会另起一个线程SpillThread往磁盘溢写,每次溢写都会产生一个数据文件和对应的索引文件。

sort过程:在溢写的过程中一直在排序,比较算法可以定制,默认排序算法是快速排序(可以人为设定),排序的过程就是一些位置的索引在不断的变化。

排序之后的数据:

<abc, 1>                 0                                          <hdfs, 1>                         1

<hello, 1>                0                                          <interface, 1>                   1

<hello, 1>                0                                          <java, 1>                          0

<hadoop, 1>             1                                         <java, 1>                         0

                                             <java, 1>                 0                                          <map, 1>                         0

                                             <jvm, 1>                  1                                         <reduce, 1>                      1

                                             <qaz, 1>                  1                                          <spark, 1>                        0

                                             <word, 1>                1                                          <storm, 1>                       1  

combine过程:这个过程默认是没有的,需要明确指定combiner。combiner其实就是一个reducer,可以让数据交给reduce任务之前,进行一些计算、合并。它的意义在于,使数据进一步减少,减轻了                       reduce任务通过网络获取数据的压力和reduce处理数据的压力。combiner也可以自己定制,每个溢写文件都会combine。

combiner会通过一个比较器对key进行比较,相同的key(比较结果为0,比较算法可以定制),会被放到一个集合的迭代器中,然后迭代进行一次reduce运算,产生一个输出。

combine之后的数据:

<abc, 1>                 0                                         <hdfs, 1>                        1

<hello, 1+1>             0                                        <interface, 1>                   1

<hadoop, 1>             1                                         <java, 1+1>                     0

                                             <java, 1>                 0                                          <map, 1>                         0

                                             <jvm, 1>                  1                                         <reduce, 1>                      1

                                             <qaz, 1>                  1                                          <spark, 1>                        0

                                             <word, 1>                1                                          <storm, 1>                       1

merge过程:一个map所有的溢写文件都会进行合并,产生一个最终的溢写文件和一个索引文件。合并是针对于不同的溢写文件中相同分区的数据。在这个合并的过程中,也会进行combine操作(如果设置了的话),此处的combine过程同上,不再细说。

copy数据过程:每个reduce任务会远程copy属于自己的多个map输出数据文件,通过http传输,在本地会合并。另外,这个过程也会进行combine,此次不过多说明。

结果如下:

reduce0                        reduce1

<abc, 1>                     <hadoop, 1>

                      <hello, 2>                    <jvm, 1>

<java, 1>                    <qaz, 1>

                      <java, 2>                     <word, 1>

<map, 1>                     <hdfs, 1>

<spark, 1>                   <interface, 1>

<reduce, 1>

<storm, 1>

sort过程:对上述结果进行排序,结果如下:

reduce0                        reduce1

<abc, 1>                     <hadoop, 1>

                       <hello, 2>                    <hdfs, 1>

<java, 1>                    <interface, 1>

                        <java, 2>                     <jvm, 1>

<map, 1>                     <qaz, 1>

<spark, 1>                   <reduce, 1>

<storm, 1>

<word, 1>

3、reduce阶段

通过一个GroupComparator对key进行比较,相同的key(比较结果为0,比较算法可以定制),会被放到一个集合的迭代器中,然后迭代进行一次reduce运算,产生一个输出。类似combine过程。

最终的输出:                     reduce0                        reduce1

<abc, 1>                     <hadoop, 1>

                       <hello, 2>                    <hdfs, 1>

<java, 3>                    <interface, 1>

                         <map, 1>                    <jvm, 1>

<spark, 1>                   <qaz, 1>

<reduce, 1>

<storm, 1>

<word, 1>

从上述过程的分析可以看出,合并和排序是核心!!!

PS:其实每个阶段没有这么分明,只不过是为了分析和理解的需要,才进行这样详细的划分,而且划分的还不一定正确,请大家及时纠错。另外,上述流程中涉及到好多的细节,没有一一说明。

MapReduce运行流程分析的更多相关文章

  1. Struts2运行流程分析

    一.Struts2运行流程图: 二.运行流程分析: 1. 请求发送给StrutsPrepareAndExecuteFilter 2.StrutsPrepareAndExecuteFilter询问Act ...

  2. 011-Spring Boot 运行流程分析SpringApplication.run

    一.程序入口 1.1.静态方法 //直接调用run方法 ConfigurableApplicationContext context = SpringApplication.run(App.class ...

  3. 【逆向&编程实战】Metasploit安卓载荷运行流程分析_复现meterpreter模块接管shell

    /QQ:3496925334 作者:MG193.7 CNBLOG博客号:ALDYS4 未经许可,禁止转载/ 关于metasploit的安卓模块,前几次的博客我已经写了相应的分析和工具 [Android ...

  4. hadoop运行流程分析源代码级

    前言: 最近一直在分析hadoop的运行流程,我们查阅了大量的资料,虽然从感性上对这个流程有了一个认识但是我总是感觉对mapreduce的运行还是没有一个全面的认识,所以决定从源代码级别对mapred ...

  5. thttpd和cgilua安装与运行流程分析

    安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...

  6. springmvc的运行流程分析

    前几篇文章对springmvc讲解的很清楚,大家看下,有问题,我们再一起讨论. 其实springmvc最为重要是它的运行流程,接着,我们来分析一下,其运行过程,废话不多说,看图说话: 分析如下: 1, ...

  7. SparkSteaming运行流程分析以及CheckPoint操作

    本文主要通过源码来了解SparkStreaming程序从任务生成到任务完成整个执行流程以及中间伴随的checkpoint操作 注:下面源码只贴出跟分析内容有关的代码,其他省略 1 分析流程 应用程序入 ...

  8. 8、Struts2 运行流程分析

    1.流程分析: 请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 ...

  9. yii框架详解 之 CWebApplication 运行流程分析

    在 程序入口处,index.php 用一句 Yii::createWebApplication($config)->run();  开始了app的运行. 那么,首先查看 CWebApplicat ...

随机推荐

  1. android Instrumentoation 问答

    android Instrumentoation 问答   1.instrumentation是执行application instrumentation代码的基类.当应用程序运行的时候instrum ...

  2. Node.js 安装配置介绍

    Node.js 安装配置 本章节我们将向大家介绍在window和Linux上安装Node.js的方法. 本安装教程以Node.js v6.10.1 LTS(长期支持版本)版本为例. Node.js安装 ...

  3. css浮动布局

    上次我们一起对盒子模型进行了一定的了解,今天我们就对css浮动布局做一下研究.首先我们来了解一下网页基本布局的三种形式. 首先我们来了解一下什么是网页布局: 网页的布局方式其实就是指浏览器是如何对网页 ...

  4. Entity Framework快速入门--ModelFirst

    Entity Framework带给我们的不仅仅是操作上的方便,而且使用上也很是考虑了用户的友好交互,EF4.0与vs2010的完美融合也是我们选择它的一个理由吧.相比Nhibernate微软这方面做 ...

  5. java 基础知识一 初识java

    java  基础知识一初识java 1.java语言的特点 (1)简洁有效(2)可移植性(3)面向对象(4)解释型(5)适合分布式计算 2.java的源文件扩展名为.java 编译后的扩展名为.cla ...

  6. 【Scala】Scala之Packaging and Imports

    一.前言 前面介绍了Scala的Object,由于中间论文的时间耽误了些时间,接着继续学习Scala的Packaging和Imports 二.Packaging and Imports Scala的包 ...

  7. java代码开发完成后,代码走查规范

    代码走查注意事项: 1.不变的值,尽量写个常量类 2.尽量使用if{}else,不要一直if去判断 3.减少循环调用方法查询数据库 4.dao层尽量不要用逻辑,尽量在service里写业务逻辑 5.金 ...

  8. 转账示例(二):service层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)

    缺点:Service层面把Dao层面的开启事务操作完成了1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; im ...

  9. SEO,搜索引擎优化原理方法等整体把握

    SEO 搜索算法: 全文文字 title 标签,title里面的文字 link 链接 link 链接里的文字 站点信任度 最佳实践: 一.设置title 准确的描述当前网页的内容 提高站点内title ...

  10. windows下批量换程序——运维常用

    Windows一批机器,需要批量换程序.写个脚本给大家. net stop sharedaccess (关闭防火墙) del /s d:\*.log d:\*.vbs d:\*.pdb d:\*.vb ...