Hadoop(4)-MapReduce原理

1. MapReduce 定义
Hadoop中的 MapReduce是一个使用简单的软件框架,基于它写出来的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错式并行处理TB级别的数据集
2. MapReduce 特点
MapReduce 之所以如此受欢迎,它主要有以下几个特点。:
- MapReduce 易于编程。它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的 PC 机器运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。 就是因为这个特点使得 MapReduce 编程变得非常流行。
- 良好的扩展性。当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。
**- 高容错性。**MapReduce 设计的初衷就是使程序能够部署在廉价的 PC 机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上面上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,而完全是由 hadoop 内部完成的。
- 适合 PB 级以上海量数据的离线处理。这里加红字体离线处理,说明它适合离线处理而不适合在线处理。比如像毫秒级别的返回一个结果,MapReduce 很难做到。
MapReduce 虽然具有很多的优势,但是它也有不擅长的地方。这里的不擅长不代表它不能做,而是在有些场景下实现的效果差,并不适合 MapReduce 来处理,主要表现在以下几个方面。
- 实时计算。MapReduce 无法像 MySQL 一样,在毫秒或者秒级内返回结果。
- 流式计算。流式计算的输入数据时动态的,而 MapReduce 的输入数据集是静态的,不能动态变化。这是因为 MapReduce 自身的设计特点决定了数据源必须是静态的。
- DAG(有向图)计算。多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce 并不是不能做,而是使用后,每个MapReduce 作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低下。

3. MapReduce的架构
目前存在两种 MapReduce 实现,分别是
• 可独立运行的 MapReduce
它由两类服务组成,分别是 JobTracker 和 TaskTraker,其中 JobTracker 存在单点故障问题,本文提到的单点故障实际上是第一种实现中JobTracker的单点故障。
• MapReduce On YARN
在这种实现中,每个作业独立使用一个作业跟踪器(ApplicationMaster),彼此之间不再相互影响,不存在单点故障问题。

下面说下可独立运行的MapReduce,和HDFS一样,MapReduce也是采用Master/Slave的架构,其架构图如下所示。
这里写图片描述
MapReduce包含四个组成部分,分别为Client、JobTracker、TaskTracker和Task,下面我们详细介绍这四个组成部分。

3.1 Client 客户端
每一个 Job 都会在用户端通过 Client类将应用程序以及配置参数 Configuration 打包成 JAR 文件存储在 HDFS,并把路径提交到 JobTracker 的 master 服务,然后由 master 创建每一个 Task(即 MapTask 和 ReduceTask) 将它们分发到各个 TaskTracker 服务中去执行。

3.2 JobTracker
JobTracke负责资源监控和作业调度。JobTracker 监控所有TaskTracker 与job的健康状况,一旦发现失败,就将相应的任务转移到其他节点;同时,JobTracker 会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可以根据自己的需要设计相应的调度器。

3. 3 TaskTracker
TaskTracker 会周期性地通过Heartbeat 将本节点上资源的使用情况和任务的运行进度汇报给JobTracker,同时接收JobTracker 发送过来的命令并执行相应的操作(如启动新任务、杀死任务等)。TaskTracker 使用“slot”等量划分本节点上的资源量。“slot”代表计算资源(CPU、内存等)。一个Task 获取到一个slot 后才有机会运行,而Hadoop 调度器的作用就是将各个TaskTracker 上的空闲slot 分配给Task 使用。slot 分为Map slot 和Reduce slot 两种,分别供Map Task 和Reduce Task 使用。TaskTracker 通过slot 数目(可配置参数)限定Task 的并发度。

3.4 Task
Task 分为Map Task 和Reduce Task 两种,均由TaskTracker 启动。HDFS 以固定大小的block 为基本单位存储数据,而对于MapReduce 而言,其处理单位是split。
Map Task 执行过程如下图 所示:由该图可知,Map Task 先将对应的split 迭代解析成一个个key/value 对,依次调用用户 自定义的map() 函数进行处理,最终将临时结果存放到本地磁盘上, 其中临时数据被分成若干个partition,每个partition 将被一个Reduce Task 处理。

Reduce Task 执行过程下图所示。该过程分为三个阶段: shuffle、sort和reduce

①Shuffle阶段:它针对多个map任务的输出按照不同的分区(Partition)通过网络复制到不同的reduce任务节点上; 
②Sort阶段:框架将按照key的值对Reducer的输入进行分组 (因为不同mapper的输出中可能会有相同的key)和排序; 
Shuffle和Sort两个阶段是同时进行的;map的输出也是一边被取回一边被合并的。
③Reduce阶段:依次读取< key, value list>,调用用户自定义的reduce() 函数处理,并将最终结果存到HDFS上。

ps:shuffle补充说明
1.shuffle的正常意思是洗牌或弄乱,Shuffle描述着数据从map task输出到reduce task输入的这段过程。Hadoop的shuffle过程就是从map端输出到reduce端输入之间的过程,包含了两端的combine和partition。
combine和partition都是函数,中间的步骤应该只有shuffle!

2.combine:Combiner号称本地的Reduce,Reduce最终的输入,是Combiner的输出。作用是把同一个key的键值对合并在一起,可以自定义的。
不使用conbiner时,reduce的输入每个key所对应的value将是一大串1,但处理的文本很多时,这一串1已将占用很大的带宽,如果我们在map的输出给于reduce之前做一下合并或计算,那么传给reduce的数据就会少很多,减轻了网络压力。此时Combiner就排上用场了。我们现在本地把Map的输出做一个合并计算,把具有相同key的1做一个计算,然后再把此输出作为reduce的输入,这样传给reduce的数据就少了很多。Combiner在系统中并没有自己的基类,Combiner是用reducer来定义的,多数的情况下Combiner和reduce处理的是同一种逻辑,他们对外的功能是一样的,只是使用的位置和使用时的上下文不太一样而已。所以job.setCombinerClass()的参数可以直接使用定义的reduce,当然也可以单独去定义一个有别于reduce的Combiner,继承Reducer,写法基本上定义reduce一样。

combine函数把一个map函数产生的< key,value >对(多个key,value)合并成一个新的< key2,value2 >.将新的< key2,value2 >作为输入到reduce函数中
这个value2亦可称之为values,因为有多个。

3.partition是分割map每个节点的结果,按照key分别映射给不同的reduce,也是可以自定义的。这里其实可以理解归类。
哪个key到哪个Reducer的分配过程,是由Partitioner规定的。它只有一个方法
getPartition(Text key, Text value, int numPartitions)
输入是Map的结果对< key, value >和Reducer的数目,输出则是分配的Reducer(整数编号)。就是指定Mappr输出的键值对到哪一个reducer上去。系统缺省的Partitioner是HashPartitioner,它以key的Hash值对Reducer的数目取模,得到对应的Reducer。这样保证如果有相同的key值,肯定被分配到同一个reducre上。如果有N个reducer,编号就为0,1,2,3……(N-1)。

4. 图解MapReduce的处理流程
MapReduce运行的时候,会通过Mapper运行的任务读取HDFS中的数据文件,然后调用自己的方法,处理数据,最后输出。Reducer任务会接收Mapper任务输出的数据,作为自己的输入数据,调用自己的方法,最后输出到HDFS的文件中。整个流程如图:
这里写图片描述
MapReduce执行过程详解
每个Mapper任务是一个Java进程,它会读取HDFS中的文件,解析成很多的键值对,经过我们覆盖的map方法处理后,转换为很多的键值对再输出。整个Mapper任务的处理过程又可以分为以下几个阶段,如图所示。
在上图中,把Mapper任务的运行过程分为六个阶段。
1.第一阶段是把输入文件按照一定的标准分片(InputSplit),每个输入片的大小是固定的。默认情况下,输入片(InputSplit)的大小与数据块(Block)的大小是相同的。如果数据块(Block)的大小是默认值64MB,输入文件有两个,一个是32MB,一个是72MB。那么小的文件是一个输入片,大文件会分为两个数据块,那么是两个输入片。一共产生三个输入片。每一个输入片由一个Mapper进程处理。这里的三个输入片,会有三个Mapper进程处理。
2.第二阶段是对输入片中的记录按照一定的规则解析成键值对。有个默认规则是把每一行文本内容解析成键值对。“键”是每一行的起始位置(单位是字节),“值”是本行的文本内容。
3.第三阶段是调用Mapper类中的map方法。第二阶段中解析出来的每一个键值对,调用一次map方法。如果有1000个键值对,就会调用1000次map方法。每一次调用map方法会输出零个或者多个键值对。
4.第四阶段是按照一定的规则对第三阶段输出的键值对进行分区。比较是基于键进行的。比如我们的键表示省份(如北京、上海、山东等),那么就可以按照不同省份进行分区,同一个省份的键值对划分到一个区中。默认是只有一个区。分区的数量就是Reducer任务运行的数量。默认只有一个Reducer任务。
5.第五阶段是对每个分区中的键值对进行排序。首先,按照键进行排序,对于键相同的键值对,按照值进行排序。比如三个键值对<2,2>、<1,3>、<2,1>,键和值分别是整数。那么排序后的结果是<1,3>、<2,1>、<2,2>。如果有第六阶段,那么进入第六阶段;如果没有,直接输出到本地的Linux文件中。
6.第六阶段是对数据进行归约处理,也就是reduce处理。键相等的键值对会调用一次reduce方法。经过这一阶段,数据量会减少。归约后的数据输出到本地的linxu文件中。本阶段默认是没有的,需要用户自己增加这一阶段的代码。

5. 图解MapReduce的处理流程
这里以WordCount单词计数为例,介绍map和reduce两个阶段需要进行哪些处理。单词计数主要完成的功能是:统计一系列文本文件中每个单词出现的次数,如图所示:
这里写图片描述

(1)map任务处理
这里写图片描述
(2)reduce任务处理
这里写图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值