本文已收录github:https://github.com/BigDataScholar/TheKingOfBigData,里面有大数据高频考点,Java一线大厂面试题资源,上百本免费电子书籍,作者亲绘大数据生态圈思维导图…持续更新,欢迎star!

前言

大家好,我是梦想家!

众所周知,Hadoop 中最核心的两大组件就是 HDFS 和 MapReduce。其中 HDFS 提供了承载海量数据存储的能力,而 MapReduce 则提供了海量数据高并行计算的能力。关于 HDFS 的介绍,之前已经写了两篇来分别介绍 HDFS 的架构 和 HDFS实现文件管理和容错的文章 。而本期文章,我将为大家介绍关于 MapReduce 的核心知识点。

MapReduce的原理

Hadoop 中 MapReduce 最核心的思想就是分而治之,通过 MapReduce 这个名字就可以看出,MapReduce 包含有 Map 和 Reduce 两个部分。它将一个大型的计算问题分解成一个个小的,简单的计算任务,交给 MapReduce 中的 Map 部分执行,随后 Reduce 部分会对 Map 部分输出的中间结果进行聚合计算,输出最终的统计结果。

为了方便大家理解,可以看下 MapReduce 的简要模型图:

        每个子任务在框架中都是高度并行计算的,然后 MapReduce 框架将各个计算子任务的计算结果进行合并,得出最终的计算结果。

每个子任务在 MapReduce 内部都是高度并行计算的,子任务的高度并行化极大地提高了 Hadoop 处理海量数据的性能。MapReduce 的并行计算模型如图所示:


        由图可知,MapReduce 框架将一个大型的计算任务拆分为多个简单的计算任务,交由多个 Map 并行计算,每个 Map 的计算结果经过中间结果处理阶段的处理后输入 Reduce 阶段,Reduce 阶段将输入的数据进行合并处理,输出最终的计算结果 。

同时,用户无须关心 MapReduce 底层各个节点之间的通信机制与通信过程,只需简单地编写 map() 函数和 reduce() 函数即可开发 Hadoop MapReduce 程度

MapReduce的部署结构

MapReduce 框架由一个主节点(ResourceManager)、多个子节点(NodeManager)和每个执行任务的 MR AppMaster 共同组成 。通常会将 MapReduce 的计算节点和存储节点部署在同一台服务器上,如图所示:


        这种部署结构可以使 MapReduce 框架在已经存储好数据的节点上快速、高效地调度任务,尽可能地不用通过 RPC 从其他服务器上获取数据来执行任务,使整个集群的网络带宽被高效利用,极大地提升了处理任务的效率

MapReduce 的运行流程

MapReduce 编程模型简化了分布式系统中并行计算的复杂度,开发人员能够不必关心 MapReduce 程序的底层实现细节,只专注于解决业务需求

在 MapReduce 框架内部,整个运行流程可以分为如下四个阶段,其中每个阶段中的数据传输格式也不一样。

简单运行流程如下所示:


        大致流程:

(1)原始数据经过 Hadoop 框架的处理,将 “(k,原始数据行)”格式的数据输入 Map 阶段,即 Map 阶段接收到的数据都是 “(k,元素数据行)”的。

(2)数据经过 Map 阶段处理之后,输出 “{(k1,v1),(k2,v2)}”格式的中间结果

(3)Map阶段输出的中间结果经由 Hadoop 的中间结果处理阶段(如聚合、排序等)之后,会形成 “ {(k1,[v1,v2]) …} ”格式的数据

(4)中间结果处理阶段形成的 “{(k1,[v1,v2]) …}”格式的数据会输入 Reduce 阶段进行处理。此时,key相同的数据会被输入进同一个 Reduce 函数进行处理(也可以由用户自定义数据分发规则)

(5)数据经过 Reduce 阶段处理之后,最终会形成“{(k1,v3)}” 格式的数据存入 HDFS 中

另外,如果觉得不够清晰,也可以参考下下面这个版本的 MapReduce 运行流程。


        (1)原始数据被切分为多个小的数据分片输入 map() 函数,这些小的数据分片往往是原始数据的数据行,它们以 “(k,line)” 的格式输入 map() 函数,其中 k 表示数据的偏移量,line 表示整行数据。

(2)map() 函数并行处理输入的数据分片,根据具体的业务规则对输入的数据进行相应的处理,输出中间处理结果,这些中间处理结果往往以“{(k1,v1),(k2,v2)}” 的格式存在。

(3)中间处理阶段将 map() 函数输出的中间结果根据 key 进行聚合处理,输出聚合结果,这些聚合结果的格式为:“{(k1,[v1,v2])}”。

(4)中间处理阶段将输出的聚合结果输入 reduce () 函数进行处理( key相同的数据会被输入同一个 reduce()函数中,用户也可以自定义数据分发规则 ),reduce()函数对这些数据进行进一步聚合和计算等。

(5)reduce 函数将最终的结果以 “ (k,v) ”的格式输出到 HDFS 中。

MapReduce的容错机制

MapReduce 容错包括 Task(任务)容错,AppMaster 容错、NodeManager 容错和 ResourceManager 容错。

1、Task 容错

AppMaster 一段时间没有收到任务进度的更新,就会将任务标记为失败,但是不会立刻杀死执行任务的进程,而是等待一定的超时时间。该超时时间可以在mapred-site.xml文件中进行配置,具体的属性为mapreduce.task.timeout

<properties><name>mapreduce.task.timeout</name><value>600000</value>
</property>

超时时间默认值为 10 min,即任务被标记为失败的 10 min 之后才会将任务失败的进程杀死。

MapReduce 提供了重试机制,重试的次数主要由 map-site.xml文件中的 mapreduce.map.maxattempts属性和mapreduce.reduce.maxattempts属性配置,代码如下所示:

<properties><name>mapreduce.map.maxattempts</name><value>4</value>
</property>
<properties><name>mapreduce.reduce.maxattempts</name><value>4</value>
</property>

默认重试次数为4,即任务失败后,MapReduce 框架会重试4次,如果任务依然失败,MapReduce才会认为任务彻底失败了。

也可以配置允许任务失败的最大百分比,可以由属性 mapreduce.map.failures.maxpercentmapreduce.reduce.failures.maxprecent 进行配置。

2、AppMaster 容错

AppMaster也提供了重试机制,YARN中的应用程序失败之后,最多尝试次数由mapred-site.xml文件中的mapreduce.am.max-attempts属性配置:

<properties><name>mapreduce.am.max-attempts</name><value>4</value>
</property>

尝试次数默认值为2,即当 AppMaster 失败2次之后,运行的任务将会失败。

在 MapReduce 内部,YARN 框架对 AppMaster 的最大尝试次数做了限制。其中,每个在 YARN 中运行的应用程序不能超过这个数量限制,具体限制由 yarn-site.xml 文件中的 yarn.resourcemanager.am.max-attempts属性控制,配置信息如下所示:

<properties><name>yarn.resourcemanager.am.max-attempts</name><value>2</value>
</property>

3、NodeManager 容错

当 NodeManager 发生故障,停止向 ResourceManager 节点发送心跳信息时,ResourceManager 节点并不会立即移除 NodeManager,而是要等待一段时间,该时间可以由 yarn.resourcemanager.nm.liveness-monitor.expiry-interval-ms 属性设置,代码如下:

<properties><name>yarn.resourcemanager.nm.liveness-monitor.expiry-interval-ms</name><value>600000</value>
</property>

等待时间默认值为 10 min,即 NodeManager 发生故障之后,ResourceManager 节点接收不到 NodeManager 发生过来的心跳信息,过 10 min 之后才会将 NodeManager 移除 。

当 NodeManager 上运行的失败任务数量达到一定的值时,AppMaster 就会将该节点上的任务调度到其他节点上。任务失败的阈值由 mapred-site.xml 文件中的 mapreduce.job.maxtaskfailures.per.tracker 属性设置,代码如下所示:

<properties><name>mapreduce.job.maxtaskfailures.per.tracker</name><value>3</value>
</property>

此默认值为3,即当一个 NodeManager 上有超过3个任务失败,AppMaster 就会将该节点上的任务调度到其他节点上 。

ResourceManager 容错

新版本的 Hadoop 中提供了 ResourceManager 节点的 HA 机制,如果主 ResourceManager 失败,备 ResouceManager 会迅速接管工作。

Hadoop 中对 ResourceManager节点提供了检查点机制,当所有的 ResourceManager 节点失败后,重启 ResouceManager 节点,可以从上一个失败的 ResourceManager 节点保存的检查点进行状态恢复。

这些检查点的存储是由 yarn-site.xml文件中的 yarn-resourcemanager.store.class属性设置的,代码如下所示:

<properties><name>yarn-resourcemanager.store.class</name><value>org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore</value>
</property>

当然,默认是保存到文件中。

MapReduce的优化

技术面试中,关于 MapReduce 优化的考察频率可能不如 Spark,Flink,但是作为 Hadoop 知识的热门考点,我们对于它的优化还是要有一个清晰的认识 。 这里,我们从以下几个小点逐一展开。

MapReduce跑的慢的原因

MapReduce程序效率的瓶颈在于两点:

  1. 计算机性能

CPU、内存、磁盘健康、网络

  1. I/O 操作优化
  • 数据倾斜
  • Map 和 Reduce 数设置不合理
  • Map运行时间太长,导致 Reduce 等待过久
  • 小文件过多
  • 大量的不可分块的超大文件
  • Spill 次数过多
  • Merge 次数过多等。

MapReduce优化

关于 MapReduce 优化方法主要从以下6个方面进行考虑,分别是:数据倾斜、Map阶段、Reduce阶段、IO传输、数据倾斜问题和常用的调优参数。

1、数据输入

(1)合并小文件:在执行 MR 任务之前将小文件进行合并,大量的小文件会产生大量的 MR 任务,增大 Map 任务装载次数,而任务的装载比较耗时,从而导致 MR 运行较慢。

(2)采用 CombineText InputFormat 来作为输入,解决输入端大量小文件场景。

2、Map阶段

(1)减少溢写(spill)次数:通过调整 io.sort.mb 及 sort.spill.percent 参数值,增大触发 Spill 的内存上限,减少 Spill 次数,从而减少磁盘 IO 。

(2)减少合并(Merge)次数:通过调整io.sort.factor参数,增大 Merge 的文件数目,减少 Merge 的次数,从而缩短 MR 处理时间。

(3)在 Map 之后,不影响业务逻辑前提下,先进行 Combine 处理,减少 I/O 。

3、Reduce 阶段

(1)合理设置 Map 和 Reduce 数:两个都不能设置的太少,也不能设置的太多。太少,会导致 Task 等待,延长处理时间;太多,会导致 Map,Reduce 任务间竞争资源,造成处理超时等错误 。

(2)设置 Map、Reduce 共存:调整 slowstart.completedmap参数,使 Map 运行到一定程度后,Reduce 也开始运行,减少 Reduce 的等待时间 。

(3)规避使用 Reduce:因为 Reduce 在用于连接数据集的时候将会产生大量的网络消耗。

(4)合理设置 Reduce 端的 Buffer:默认情况下,数据达到一个阈值的时候,Buffer 中的数据就会写入磁盘,然后 Reduce 会从磁盘中获得所有的数据。也就是说,Buffer 和 Reduce 是没有直接关联的,中间多次写磁盘 -> 读磁盘的过程,既然有这个弊端,那么就可以通过参数来配置,使得 Buffer 中的一部分数据可以直接输送到 Reduce,从而减少 IO 开销 : mapreduce.reduce.input.buffer.percent,默认为 0.0 。当值大于 0 的时候,会保留指定比例的内存读 Buffer 中的数据直接拿给 Reduce 使用 。 这样一来,设置 Buffer 需要内存,读取数据需要内存,Reduce 计算也需要内存,所以要根据作业的用运行情况进行调整 。

4、I/O 传输

(1)采用 数据 压缩的方式,减少 网络 IO 的时间 。 安装 Snappy 和 LZO 压缩编码器。

(2)使用 SequenceFile 二进制文件。

5、数据倾斜问题

1. 数据倾斜现象:
  • 数据频率倾斜——某一个区域的数据量要远远大于其他的区域。
  • 数据大小倾斜——部分记录的大小远远大于平均值
2.减少数据倾斜的方法:
方法1 :抽样和范围分区

可以通过对原始数据进行抽样得到的结果集来预设分区边界值。

方法2:自定义分区

基于输出键的背景知识进行自定义分区。例如,如果 Map 输出键的单词来源于一本书。且其中某几个专业词汇较多,那么就可以自定义分区将这些专业词汇发送给固定的一部分 Reduce 实例。而其他的都发送给剩余的 Reduce 实例。

方法3:Combine

使用 Combine 可以大量的减少数据倾斜。在可能的情况下,Combine 的目的就是聚合并精简数据。

方法4:采用 Map Join,尽量避免 Reduce Join

这个我们上面说过了,Reduce 在用于连接数据集的时候将会产生大量的网络消耗,所以我们采用 MapJoin,尽量避免 Reduce Join 。

6、常用的调优参数

1、资源相关参数

(1)以下参数是在用户自己的MR应用程序中配置就可以生效(mapred-default.xml

配置参数 参数说明
mapreduce.map.memory.mb 一个MapTask可使用的资源上限(单位:MB),默认为1024。如果MapTask实际使用的资源量超过该值,则会被强制杀死。
mapreduce.reduce.memory.mb 一个ReduceTask可使用的资源上限(单位:MB),默认为1024。如果ReduceTask实际使用的资源量超过该值,则会被强制杀死。
mapreduce.map.cpu.vcores 每个MapTask可使用的最多cpu core数目,默认值: 1
mapreduce.reduce.cpu.vcores 每个ReduceTask可使用的最多cpu core数目,默认值: 1
mapreduce.reduce.shuffle.parallelcopies 每个Reduce去Map中取数据的并行数。默认值是5
mapreduce.reduce.shuffle.merge.percent Buffer中的数据达到多少比例开始写入磁盘。默认值0.66
mapreduce.reduce.shuffle.input.buffer.percent Buffer大小占Reduce可用内存的比例。默认值0.7
mapreduce.reduce.input.buffer.percent 指定多少比例的内存用来存放Buffer中的数据,默认值是0.0

(2)应该在YARN启动之前就配置在服务器的配置文件中才能生效(yarn-default.xml

配置参数 参数说明
yarn.scheduler.minimum-allocation-mb 给应用程序Container分配的最小内存,默认值:1024
yarn.scheduler.maximum-allocation-mb 给应用程序Container分配的最大内存,默认值:8192
yarn.scheduler.minimum-allocation-vcores 每个Container申请的最小CPU核数,默认值:1
yarn.scheduler.maximum-allocation-vcores 每个Container申请的最大CPU核数,默认值:32
yarn.nodemanager.resource.memory-mb 给Containers分配的最大物理内存,默认值:8192

(3)Shuffle性能优化的关键参数,应在YARN启动之前就配置好(mapred-default.xml

配置参数 参数说明
mapreduce.task.io.sort.mb Shuffle的环形缓冲区大小,默认100m
mapreduce.map.sort.spill.percent 环形缓冲区溢出的阈值,默认80%
2、容错相关参数(MapReduce性能优化)
配置参数 参数说明
mapreduce.map.maxattempts 每个Map Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。
mapreduce.reduce.maxattempts 每个Reduce Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。
mapreduce.task.timeout Task超时时间,经常需要设置的一个参数,该参数表达的意思为:如果一个Task在一定时间内没有任何进入,即不会读取新的数据,也没有输出数据,则认为该Task处于Block状态,可能是卡住了,也许永远会卡住,为了防止因为用户程序永远Block住不退出,则强制设置了一个该超时时间(单位毫秒),默认是600000。如果你的程序对每条输入数据的处理时间过长(比如会访问数据库,通过网络拉取数据等),建议将该参数调大,该参数过小常出现的错误提示是“AttemptID:attempt_14267829456721_123456_m_000224_0 Timed out after 300 secsContainer killed by the ApplicationMaster.”

巨人的肩膀

1、《海量数据处理与大数据技术实战》
2、《Hadoop权威指南》

小结

实际上,关于 MapReduce的内容还有很多,本期文章只是将比较重要核心的部分介绍了一下。其中,MapReduce的原理,运行流程,优化是面试中比较经常考察的点,而部署结构,容错机制我们仅做学习了解即可。我还想强调一点,一定要学会自发的去学习新的知识和总结学过的内容。否则就容易出现,新学的记不住,学过的忘记了的情况。

好了,本期文章就到这里,我是梦想家,我们下一期见!如果对您有所帮助,请记得一键三连~

MapReduce 的核心知识点,你都 get 到了吗 ?(干货文章,建议收藏!)相关推荐

  1. Python所有的库都在这里了!!强烈建议收藏

    前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 随着大数据和人工智能的发展,Python也与多种科技深深绑定. 比如自动化测试,运维,爬虫,数据分析,机器学习,金融领域,后端 ...

  2. Linux史上最全(30000字)知识点总结,含部署环境搭建步骤(建议收藏后看)

    认识Linux 入门概述 我们为什么要学习Linux linux诞生了这么多年,以前还喊着如何能取代windows系统,现在这个口号已经小多了,任何事物发展都有其局限性都有其天花板.就如同在国内再搞一 ...

  3. 熬夜爆肝!C++核心STL常用算法汇总整理【2W字干货预警 建议收藏】

    前言 1 STL- 常用算法 1.1 常用遍历算法 1.1.1 for_each 1.1.2 transform 1.2 常用查找算法 1.2.1 find 1.2.2 find_if 1.2.3 a ...

  4. 神级程序员都在用什么工具?【建议收藏】

    Apifox 最好用的接口管理神器,没有之一,秒杀市面上所有同类产品. Apifox 是 API 文档.API 调试.API Mock.API 测试一体化协作平台,定位 Postman + Swagg ...

  5. ❤️爆肝熬夜开发了一个SpringBoot活动管理系统,现在开源给你!毕设面试学习都不愁了!【强烈建议收藏】❤️

    前面有个粉丝找到猛哥,说遇到了困难!让我开发一个基于springboot的活动管理系统! 他非常的着急,事情比较突然. 好吧,我去买了咖啡,熬了两个通宵给赶制出来了! 后来小伙伴用完系统后,他说可以开 ...

  6. 奉劝那些刚参加工作的学弟学妹们:要想进大厂,这些并发编程核心技能是你必须要掌握的!!(建议收藏)

    大家好,我是冰河~~ 最近有很多学弟学妹问我:冰河,并发编程要学哪些内容呀?我看你CSDN博客的的[精通高并发系列]更新了很多高并发编程的技术文章,你是怎么学习的呢?后面你还会更新吗?啥时候更新完呀? ...

  7. 【星球知识卡片】人脸属性编辑都有哪些核心知识点,如何长期进行学习

    大家好,欢迎来到我们的星球知识小卡片专栏,本期给大家分享人脸属性编辑的核心技术点. 作者&编辑 | 言有三 1 人脸表情编辑 人脸表情编辑即更改脸部的表情属性,包括嘴唇.鼻子等区域.可以广泛应 ...

  8. 透过面试题,洞察Hbase 核心知识点

    LSM  算法 HFile 索引 ,二级索引 hbase的问题 1.hbase怎么预分区? 2.hbase怎么给web前台提供接口来访问? 3.htable API有没有线程安全问题,在程序中是单例还 ...

  9. hadoop---(1)hadoop核心知识点总结

    hadoop核心知识点总结 1.  安装hadoop需要配置的hadoop中的配置文件有哪些? hadoop-env.sh yarn-env.sh core-site.xml hdfs-site.xm ...

最新文章

  1. xib 拖关联控件的时候报Could not insert new outlet connection错误
  2. python 验证码识别示例(二) 复杂验证码识别
  3. Android之线程池深度剖析
  4. Ubuntu 卸载 Nvidia 驱动和安装最新驱动
  5. Android 如何实现带滚动条的TextView,在更新文字时自动滚动到最后一行
  6. asp.net导出GridView数据到Excel
  7. [省选联考 2020 A/B 卷] 信号传递(状压dp + 卡空间)
  8. element解决表格错位问题
  9. vantUI组件:获取验证码 - 踩坑篇
  10. html双箭头菜单,CSS常用样式之绘制双箭头的示例代码
  11. 【IBM Tivoli Identity Manager 学习文档】14 TIM组织结构设计
  12. 2010年ImagineCup,我们共同走过
  13. keil5新建STM32工程文件--实践篇手把手教学(以STM32F103为例)
  14. Keras中Conv1D和Conv2D的区别
  15. ​数据科学家必须了解的事:中心极限定理
  16. win10怎么找回永久删除的文件
  17. 听VOA还不如学这些
  18. android 开发微信群发,Android 记录一次开发微信分享功能的吐槽与思考
  19. Smart3D将已经生成的OSGB格式的模型转换成S3C格式
  20. 药物研发统计师的一天(试验设计篇)

热门文章

  1. Django 学习 之ORM多表操作
  2. Python 两种POST请求的方式
  3. uni-app升级APP,包含apk整包升级和wgt应用资源升级
  4. Uncaught (in promise) TypeError: Cannot read property 'data' of undefined
  5. 子午圈和卯酉圈的定义
  6. 学习了网络营销信息传递原理,如何应用于就业求职?
  7. C++为什么需要高精度计算
  8. 开源聚合路由 OpenMPTCProuter 配置使用
  9. Java中使用MVC三层架构做登陆验证
  10. 计算机网络课程设计(模拟总公司、分公司的局域网)