从零学习MapReduce—Hadoop生态圈(二)

MapReduce

1.MapReduce定义

        MapReduce是一个并行计算与运行软件框架(Software Framework)。它提供了一个庞大但设计精良的并行计算软件框架,能自动完成计算任务的并行化处理,自动划分计算数据和计算任务,在集群节点上自动分配和执行任务以及收集计算结果,将数据分布存储、数据通信、容错处理等并行计算涉及到的很多系统底层的复杂细节交由系统负责处理,大大减少了软件开发人员的负担。

2.MapReduce优点&缺点

MapReduce优点

  • MapReduce易于编程:需要实现一些简单接口,就可以完成一个分布式程序
  • 良好的扩展性:通过简单的增加机器(nodemanager)来扩展它的计算能力
  • 高容错性,一台datanode上的任务失败后,可以转移到另外一台datanode上执行;
  • 适合海量数据的离线分析:

.MapReduce缺点

  • 不擅长实时计算:无法像MySQL一样,在毫秒或者秒级内返回结果
  • 不擅长流式计算:流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态变化。
  • 不擅长DAG有向图计算:多个应用程序之间存在依赖关系,后一个应用程序的输入为前一个程序的输出。在这种情况下,每个MapReduce作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常低下

3.MapReduce工作流程

下图为MapReduce整体工作流程:

在这里插入图片描述
        一个MapReduce程序启动的时候,最先启动的是MRAppMaster,MRAppMaster启动后根据本次job的描述信息,计算出需要的maptask实例数量,然后向集群申请机器启动相应数量的maptask进程:
        一个job的Maptask阶段并行度由客户端在提交job时决定,而客户端对map阶段并行度的规划的基本逻辑为:

  • 将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分成逻辑上的多个split),然后每一个split分配一个mapTask并行实例处理;
  • 这段逻辑及形成的切片规划描述文件,由FileInputFormat实现类的getSplits()方法完成,其过程如下图:

在这里插入图片描述


        接下来分为MapTask端和ReduceTask端来遍历整个流程,下图为MapTask端工作流程:

在这里插入图片描述


  • MapTask端工作流程:
    • Read阶段:MapTask通过用户编写的RecordReader,通过调用read()方法从输入InputSplit中解析出一个个key/value值;
    • Mapper阶段:该节点主要是将从Read阶段解析出的key/value值交给用户编写map()函数处理,并产生一系列新的key/value值(每一个Read阶段产生的key/value都会创建一个Mapper对象),通过调用Mapper的context.write()方法输出到OutputCollector收集器;
    • Collect阶段:OutputCollector通过调用collect()方法收集key/value值,在该函数内部,它会将生成的key/value分区(调用Partitioner :对于Mapper输出的每一个键值对,系统都会给定一个partition,partition值默认是通过计算key的hash值后对ReduceTask的数量取模获得。如果一个键值对的partition值为1,意味着这个键值对会交给第一个Reducer处理),之后将key/value值发送至环形内存缓冲区,此阶段后正式进入Maptask端的shuffer;
    • Spill(溢写)阶段:不断地将键值对输出到在内存中构造的一个环形数据结构中(使用环形数据结构是为了更有效地使用内存空间,在内存中放置尽可能多的数据),也可称为环形缓冲区;这个数据结构其实就是个字节数组叫Kvbuffer,默认大小100M(可以通过mapreduce.task.io.sort.mb(default:100)参数来调整),spill一般会在Buffer空间大小的80%(可以通过mapreduce.map.sort.spill.percent(default:0.80)进行调整)开始进行spill(因为spill的时候还有可能别的线程在往里写数据,因为还预留空间,有可能有正在写到Buffer中的数据),MapTask在计算的时候会不断产生很多spill文件;
    • Merge阶段:将很多的spill文件合并为一个大文件;在合并的过程中,)在溢出过程及合并的过程中,都要调用 Partitioner进行分区和针对 key进行排序 sort,还有可能增加的Combiner合并,针对有设置Combiner操作的,不同分区内根据相同key的key/value,调用reduce()方法,将相同key的key/value进行合并(Merge阶段如果有大量spill文件,无法一次完成整个merge的过程,这个时候需要调大mapreduce.task.io.sort.factor(default:10)来减少merge的次数,从而减少磁盘的操作);

        下图为ReduceTask端工作流程:
在这里插入图片描述

  • ReduceTask端工作流程:
    • Copy阶段:Reduce任务通过HTTP向各个MapTask任务拖取它所需要的数据。MapTask任务成功完成后,会通知父TaskTracker状态已经更新,TaskTracker进而通知JobTracker(这些通知在心跳机制中进行)。所以,对于指定作业来说,JobTracker能记录MapTask的输出和TaskTracker的映射关系。Reduce会定期向JobTracker获取MapTask的输出位置,一旦拿到输出位置,Reduce任务就会从此输出对应的TaskTracker上复制输出到本地,而不会等到所有的MapTask任务结束。
    • MergeSort(排序合并)阶段:Copy过来的数据会先放入内存缓冲区中,如果内存缓冲区中能放得下这次数据的话就直接把数据写到内存 中,即内存到内存merge;Reduce要向每个Map去拖取数据,在内存中每个Map对应一块数据 ,当内存缓存区中存储的Map数据占用空间达到一定程度的时候,开始启动内存中merge,把内存中的数据merge输出到磁盘上一个文件中,即内存到磁盘merge;当属于该reducer的map输出全部拷贝完成,则会在 reducer上生成多个文件(如果拖取的所有map数据总量都没有超出内存缓冲区,则数据就只存在于内存中),这时开始执行合并操作,即磁盘到磁盘merge,Map的输出数据已经是有序的,Merge进行一次合并排序,所谓Reduce端的sort过程就是这个合并的过程;一般Reduce是一边copy一边sort,即copy和sort两个阶段是重叠而不是完全分开的。至此,Reduce端的shuffer结束,最终Reduce shuffle过程会输出一个整体有序的数据块。
    • Reduce阶段:Reduce从合并的文件中取出一个一个的键值对 group,调用用户自定义的reduce()方法,生成最终的输出文件。

PS:如果有写错或者写的不好的地方,欢迎各位大佬在评论区留下宝贵的意见或者建议,敬上!如果这篇博客对您有帮助,希望您可以顺手帮我点个赞!不胜感谢!

原创作者:wsjslient

作者主页:https://blog.csdn.net/wsjslient

参考来源:https://blog.csdn.net/zuochang_liu/article/details/81842773

                   https://blog.csdn.net/zhongqi2513/article/details/78321664

                   https://blog.csdn.net/u014374284/article/details/49205885

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值