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

转载于:https://www.cnblogs.com/cz123/p/5447569.html

MapReduce运行流程分析相关推荐

  1. SpringMVC运行流程分析

    一.运行流程图 下面是 SpringMVC 运行流程的分析图,包括了拦截器的调用过程,目标资源的处理以及异常处理. 二.运行流程中的相关组件 在上面的流程图中有几个比较重要的组件,下面大概描述一下其对 ...

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

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

  3. WordPress 运行流程分析

    2019独角兽企业重金招聘Python工程师标准>>> WordPress 的运行流程如下图所示: 整个wp的程序结构比较特别,也不象一些普通的面向过程,也不是MVC,总之就是他自己 ...

  4. vue3 源码分析-运行流程分析

    虚拟dom和代理可以参考其他博客,此博客介绍vue3运行流程.方便理解vue的运行流程. 一.初次渲染流程 const createApp = ((...args) => {const app ...

  5. ecos运行流程分析

    先实践后理论,我使用一块CPE301G-QCA9535的开发板进行分析.这块开发板是在开发中的ecos. 一)宏观分析ecos的运行 我们从启动日志入手,去一步一步了解ecos的运行. 总所周知,板子 ...

  6. 对mapreduce分布式计算框架原理,进行完整流程分析

    本文中大致的对mapreduce进行完整流程分析,map.reduce端的分析. 一. MapReduce 简介 MapReduce源自google的一篇文章,将海量数据处理的过程拆分为map和red ...

  7. HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程

    在<HDFS源码分析心跳汇报之数据结构初始化>一文中,我们了解到HDFS心跳相关的BlockPoolManager.BPOfferService.BPServiceActor三者之间的关系 ...

  8. Apache Shiro的运行流程和权限控制方式分析

    Apache Shiro的运行流程和权限控制方式分析 Shiro的架构有3个主要的概念: Subject SecurityManager Realms 下面的关系图是关于这些组件是如何交互的高级概述. ...

  9. STM32的完整启动流程分析-----在外存flash中运行代码

    1. 根据boot引脚决定三种启动模式 复位后,在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值.BOOT0 为专用引脚,而 BOOT1 则与 GPIO 引脚共用.一旦完成对 BOOT1 的采 ...

  10. 【生产者分析五】Sender线程运行流程初探

    生产者源码之Sender线程运行流程初探 前面已经介绍到了Sender线程,元数据就是通过Sender线程发送网络请求,获取到的.有了元数据之后,就可以实现把消息发送给kafka集群中,下面我们来分析 ...

最新文章

  1. hibernate:无法级联插入
  2. iOS开发tableview二级联动的细节实现中注意的细节总结
  3. Myeclipse编译工程用Weblogic发布的时候jdk版本问题
  4. 如何从Debian 9 Stretch 升级到 Debian 10 Buster(升级Debian9图文教程)
  5. 蓝桥杯 ALGO-115 算法训练 和为T Java版
  6. CentOS下ELK收集Nginx日志
  7. II.MongoDB CRUD Operations(CRUD操作)
  8. AjaxPro.NET实现TextBox智能获取服务端数据功能(Asp.net 2.0)(示例代码下载)
  9. python识别数字程序_Python识别处理照片中的条形码
  10. 点击area不出现黑框_一切小黑屋,都能被黑框玻璃门治愈 | 附安装法则
  11. Torch环境搭建遇到的问题
  12. oracle自我评价简历,程序员简历自我评价
  13. 翻译pdf中的英文 python_看不懂pdf中的英文?就用Python
  14. 【环境配置】octopus + dirt--ubuntu18.04
  15. Stratified Transformer复现和调试记录,ubuntu20复现S3DIS数据集(点云语义分割)
  16. 微信小程序 评论功能实现
  17. Centos7 安装Vpp 及一些学习资料。
  18. 6种改善客户体验的方法
  19. 搜索引擎 Solr 简介
  20. 受关注的两个投资市场就是港股和美股

热门文章

  1. 在 Mac 上的 Safari 浏览器中如何存储网页的一部分或整个网页?
  2. Mac上如何使用Rss阅读器个性化订阅网站最新内容?
  3. WIDOWS 7全家桶(很详细)
  4. SQL 四舍五入 同时取规定小数位的数值
  5. CentOS 7 安装开发者环境
  6. Python爬虫(一)抓取指定的页面
  7. JavaScript中的[]和{}
  8. Linux命令----rpm
  9. SQL Server 2012 扩展事件(2)体系结构
  10. 红帽RHEL5U4平台实现pppoe+freeradius+mysql认证服务器(一)