关闭

MapReduce原理

标签: hadoop大数据性能优化mapreduce分布式文件系统
260人阅读 评论(0) 收藏 举报
分类:

1、MapReduce简介

MapReduce是现今一个非常流行的分布式计算框架,它被设计成用于并行计算海量数据,第一个提出该技术框架的是Google公司,MapReduce框架的核心步骤主要分两部分:Map和Reduce,当你向MapReduce提交一个计算作业时,它会首先把计算作业拆分成若干个Map任务,然后分配到不同的节点上去执行,每一个Map任务处理输入数据中的一部分,当Map任务完成后,会生产一些中间文件,这些中间文件将会作为Reduce任务的输入数据,Reduce的任务主要目标就是把前面若干个Map的输出汇总到一起并输出,从高层抽象来看,MapReduce的数据流图如下图所示:


2、MapReduce流程分析


2.1 Map过程

  1. 每一个输入分片会让一个Map任务来处理,默认情况下,以HDFS的一个块的大小(默认为64MB)为一个分片,当然我们也可以设置块的大小。Map输出的结果会暂且放在一个环形内存缓冲区中(该缓冲区的大小默认为100M,由io.sort.mb属性控制),当该缓冲区快要溢出时(默认缓冲区大小的80%,由Io.sort.spill.percent属性控制),会在本地文件系统中创建一个溢出文件,将该缓冲区的数据写入到这个文件中;
  2. 在写入磁盘之前,线程首先会根据reduce任务的数目划分相同数目的分区,也就是一个reduce任务对应一个分区的数据。这样做就是为了避免有些reduce任务分配到大量数据,而有些reduce分配到很小的数据,甚至没有数据。其实分区就是对数据进行hash的过程,然后对每个分区中的数据进行排序,如果此时设置了combiner,将排序后的结果进行Combia操作,这样做的目的是让尽可能少的数据写入到磁盘;
  3. 当Map任务输出到最后一个记录是,可能会有很多的溢出文件,这时需要将这些文件合并,合并的过程中会不断进行排序和combia操作,目的有两个:
  4. 将分区中的数据拷贝给相对应的reduce任务,有人可能会问:分区中的数据怎么知道它对应的reduce呢?其实Map任务一直和其父TaskTracker保持联系,而TaskTracker又一直和JobTracker保持心跳,所以JobTracker中保存了整个集群中的宏观信息,只要reduce任务向JobTracker获取对应的Map输出位置就可以了。
    • 尽量减少每次写入磁盘的数据量;
    • 尽量减少下一复制阶段网络传输的数据量,最后合并成了一个已分区已排序的文件,为了减少网络传输的数据量,这里可以将数据压缩,只要将Mapred.compress.map.out设置为true就可以。
2.2 Reduce过程
  1. Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接收的数据量相当小,则直接存储在内存中(缓冲区大小由mapred.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中;
  2. 随着溢写文件的增多,后台线程会将他们合并成一个更大的有序文件,这样做是为了给后面的合并节省时间,其实不管在map端还是reduce端,MapReduce都是反复地执行排序,合并操作;
  3. 合并的过程中会产生许多的中间文件(写入磁盘了),但MapReduce会让写入磁盘的数据尽可能地少,并且最后一次合并的结果并没有写入磁盘,而是直接输入到reduce函数。
  1. Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接受的数据量相当小,则直接存储在内存中(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中;
2.3 MapReduce工作机制剖析

  1. 在集群中的任意一个节点提交MapReduce程序;
  2. JobClient收到作业后,JobClient向JobTracker请求获取一个Job ID;
  3. 将运行作业所需的资源文件复制到HDFS上(包括MapReduce程序打包的JAR文件,配置文件和客户端计算所得的输入划分信息),这些文件都从放在JobTracker专门为该作业创建的文件夹中,文件夹名为该作业的Job ID;
  4. 或得作业ID后,提交作业;
  5. JobTracker接收到作业后,将其放在一个作业队列中,等待作业调度器进行调度,当作业调度器根据自己的调度算法调度到该作业时,会根据输入划分信息为一个划分创建一个map任务,并将map任务分配给TaskTracker执行;
  6. 对于Map和Reduce任务,TaskTracker根据主机的数量和内存大小有固定数量的map槽和reduce槽,这里需要强调的是:map任务不是随随便便地分配给某个TaskTracker的,这里有个概念叫:数据本地化(Data-Local)。意思是:将map任务分配给含有该map处理的数据块的TaskTacker上,同时将程序JAR包复制到该TaskTacker上来运行,这叫“运算移动,数据不移动”;
  7. TaskTracker每隔一段时间会给JobTacker发送一个心跳,告诉JobTracker她依然在运行,同时心跳中还携带者很多的信息,比如当前map任务的进度等信息。当JobTacker收到作业的最后一个任务完成信息时,便把该作业设置成“成功”。当JobClient查询状态时,他将得知任务以完成,便显示一条消息给用户;
  8. 运行的TaskTracker从HDFS中获取运行所需的资源,这些资源包括MapReduce程序打包的JAR文件、配置文件和客户端计算所得的输入划分等信息;
  9. TaskTracker获取资源后启动新的JVM虚拟机;
  10. 运行每一个任务;

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20017次
    • 积分:475
    • 等级:
    • 排名:千里之外
    • 原创:25篇
    • 转载:13篇
    • 译文:0篇
    • 评论:0条