为了更详细地探讨mapper和reducer之间的关系,并揭示Hadoop的一些内部工作机理,现在我们将全景呈现WordCount是如

何执行的,序号并非完全按照上图。

1 . 启动

调用驱动中的Job.waitForCompletion()是所有行动的开始。该驱动程序是唯一一段运行在本地机器上的代码,上述调用开

启了本地主机与JobTracker的通信。请记住,JobTracker负责作业调度和执行的各个方面,所以当执行任何与作业管理相关的

任务时,它成为了我们的主要接口,JobTracker代表我们与NameNode通信,并对储存在HDFS上的数据相关的所有交互进行

管理。


2 . 将输入分块

这些交互首先发生在JobTracker接受输入数据,并确定如何将其分配给map任务的时候。回想一下,HDFS文件通常被分

成至少64MB的数据块,JobTracker会将每个数据块分配给一个map任务。

当然,WordCount示例涉及的数量是微不足道的,它刚好适合放在一个数据块中。设想一个更大的以TB为单位的输入文

件,切分模型变得更有意义。每段文件(或用MapReduce术语来讲,每个split)由一个map作业处理。

一旦对各分块完成了运算,JobTracker就会将它们和包含Mapper与Reducer类的JAR文件放置在HDFS上作业专用的目

录,而该路径在任务开始时将被传递给每个任务。


3 . 任务分配

一旦JobTracker确定了所需的map任务数,它就会检查集群中的主机数,正在运行的TaskTracker数以及可并发执行的

map任务数(用户自定义的配置变量)。JobTracker也会查看各个输入数据块在集群中的分布位置,并尝试定义一个执行计

划,使TaskTracker尽可能处理位于相同物理主机上的数据块。或者即使做不到这一点,TaskTracker至少处理一个位于相同

硬件机架中的数据块。

数据局部优化是Hadoop能高效处理巨大数据集的一个关键原因。默认情况下,每个数据块会被复制到三台不同主机。

所以,在本地处理大部分数据块的任务/主机计划比起初预想的可能性更高。

4 . 任务启动

然后,每个TaskTracker开启一个独立的Java虚拟机来执行任务。这确实增加了启动时间损失,但它将因错误运行map

或reduce任务所引发的问题与TaskTracker隔离开来,而且可以将它配置成在随后执行的任务之间共享。

如果集群有足够的能力一次性执行所有的map任务,它们将会被全部启动,并获得它们将要处理的分块数据和作业JAR文

件。每个TaskTracker随后将分块复制到本地文件系统。

如果任务数超出了集群处理能力,JobTracker将维护一个挂起队列,并在节点完成最初分配的map任务后,将挂起任务分

配给节点。

现在,我们准备查看map任务执行完毕的数据。听起来工作量似乎很大,事实却是如此。这也解释了在运行任意

MapReduce作业时,为什么系统启动及执行上述步骤会花费大量时间。

5 . 不断监视JobTracker

现在,JobTracker执行所有的mapper和reducer。它不断地与TaskTracker交换心跳和状态消息,查找进度或问题的证

据。它还从整个作业执行过程的所有任务中收集指标,其中一些指标是Hadoop提供的,还有一些是map和reduce任务的开发

人员指定的,不过本例中我们没有使用任何指标。

6 . mapper的输入

假设输入文件是一个极为普通的两行文本文件。

This is  a  test.

Yes this is

驱动类使用TextInputFormat指定了输入文件的格式和结构,因此,Hadoop会把输入文件看做以偏移量为键并以该行内容

为值的文本。因此mapper的两次调用将被赋予以下输入。

0  This is a test.

15  Yes  this  is

7 . mapper的执行

根据作业配置的方式,mapper接收到的键/值对分别是相应行在文件中多我们不关心每行文本在文件中的位置,所以

WordCountMapper类的map方法舍弃了键,并使用标准的Java String类的split方法将每行文本内容拆分成词。需要注意的是,

使用正则表达式或StringTokenizer类可以更好地断词,但对于我们的需求,这种简单的方法就足够了。

然后,针对每个单独的词,mapper输出由单词本身组成的键和值1。

注意:

以静态变量的形式创建IntWritable对象,并在每次调用时复用该对象。这样做的原因是,尽管它对我们小型的输入文件帮助不大,但处理巨大数

据集时,可能会对mapper进行成千上万次调用。如果每次调用都为输出的键和值创建一个新对象,这将消耗大量的资源,同时垃圾回收会引发更频繁

的停滞。我们使用这个值,知道Context .write方法不会对其进行改动。

8 . mapper的输出和reducer的输入

mapper的输出是一系列形式为(word,1)的键值对。本例中,mapper的输出为:

( This , 1 ) , ( is , 1 ) , ( a , 1 ) , ( test. , 1 ) , ( Yes , 1 ) , ( this , 1 ) , ( is , 1 )

这些从mapper输出的键值对并不会直接传给reducer。在map和reduce之间,还有一个shuffle阶段,这也是许多

MapReduce奇迹发生的地方。

9 . 分块

Reduce接口的隐性保证之一是与给定键相关的所有值都会被提交到同一个reducer。由于一个集群中运行着多个reduce

任务,因此,每个mapper的输出必须被分块,使其分别传入相应的各个reducer。这些分块文件保存在本地节点的文件系统。

集群中的Reduce任务数并不像mapper数量一样是动态,事实上,我们可以在作业提交阶段指定reduce任务数。因此,每

个TaskTracker就知道集群中有多少个reducer,并据此得知mapper输出应切为多少块。

假如reducer失败了,会给本次计算带来什么影响呢?

JobTracker会保证重新执行发生故障的reduce任务,可能是在不同的节点重新执行,因此临时故障不是问题。更为严重的

问题是,数据块中的数据敏感性缺陷或错误数据可能导致整个作业失败,除非采取一些手段。

10 . 可选分块函数

Partitioner类在org.apache.hadoop.mapreduce包中,该抽象类具有如下特征:

public abstract class Partitioner<Key, Value>{public abstract int getPartition( Key key, Value value,int numPartitions);
}

默认情况下,Hadoop将对输出的键进行哈希运算,从而实现分块。此功能由org.apache.hadoop.mapreduce.lib.

partition包里的HashPartitioner类实现,但某些情况下,用户有必要提供一个自定义的partitioner子类,在该子类中实现针对具

体应用的分块逻辑。特别是当应用标准哈希函数导致数据分布极不均匀时,自定义partitioner子类尤为必要。

11 . reducer类的输入

reducer的TaskTracker从JobTracker接收更新,这些更新指明了集群中哪些节点承载着map的输出分块,这些分块将由本

地reduce任务处理。之后,TaskTracker从各个节点获取分块,并将它们合并为一个文件反馈给reduce任务。

12 . reducer类的执行

我们实现的WordCountReducer类很简单。针对每个词,该类仅对数组中的元素数目进行统计并为每个词输出最终的

(Word,count)键值对。

reducer的调用次数通常小于mapper的调用次数,因此调用reducer带来的开销无需特别在意。

13 . reducer类的输出

因此,本例中的 reducer的最终输出集合为:

( This , 1 ),( is , 2 ) , ( a , 1 ) , ( test. , 1 ) , ( Yes , 1 ) , ( this , 1 )

这些数据将被输出到驱动程序指定的输出路径下的分块文件中,并将使用指定的OutputFormat对其进行格式化。每个

reduce任务写入一个以part -r-nnnnn为文件名的文件,其中nnnnn从00000开始并逐步递增。

14 . 关机    

一旦成功完成所有任务,JobTracker向客户端输出作业的最终状态,以及作业运行过程中一些比较重要的计数器集合。

完整的作业和任务历史记录存储在每个节点的日志路径中,通过JobTracker的网络用户接口更易于访问,只需将浏览器指向

JobTracker节点的50030端口即可。

15 . 这就是MapReduce的全部

如你所见,Hadoop为每个MapReduce程序提供了大量机制,同时,Hadoop提供的框架在许多方面都进行了简化。如前

所述,对于WordCount这样的小程序来说,MapReduce的大部分机制并没有多大价值,但是不要忘了,无论在本地Hadoop或

是集群上,我们可以使用相同的软件和mapper/reducer在巨大的集群上对更大的数据集进行字数统计。那时,Hadoop所做的

大量工作使用户能够在如此大的数据集上进行数据分析。否则,手工实现代码分发、代码同步以及并行运算将付出超乎想象的

努力。

16 . 也许缺了combiner

前面讲述了MapReduce程序运行的各个步骤,却漏掉了另外一个可选步骤。在reducer获取map方法的输出之前,

Hadoop允许使用combiner类对map方法的输出执行一些前期的排序操作。

为什么要有combiner?

Hadoop设计的前提是,减少作业中成本较高的部分,通常指磁盘和网络输入输出。mapper的输出往往是巨大的---它的大

小通常是原始输入数据的许多倍。Hadoop的一些配置选项可以帮助减少reducer在网络上传输如此大的数据带来的性能影响。

combiner则采取了不同的方法,它对数据进行早期聚合以减少所需传输的数据量。

combiner没有自己的接口,它必须具有与reducer相同的特征,因此也要继承org.apache.hadoop.mapreduce包里的

Reduce类。这样做的效果主要是,在map节点上对发往各个reducer的输出执行mini-reduce操作。

Hadoop不保证combiner是否被执行。有时候,它可能根本不执行,而某些时候,它可能被执行一次、两次甚至多次,这

取决与mapper为每个reducer生成的输出文件的大小和数量。

参自《Hadoop基础教程》

学之,以记之。

转载于:https://www.cnblogs.com/baalhuo/p/5762088.html

MapReduce程序的运行全貌相关推荐

  1. mapreduce程序本地运行,单词统计案例

    mapreduce程序本地运行单词统计案例,输入输出数据放在本地 集群模式运行:https://blog.csdn.net/weixin_43614067/article/details/108400 ...

  2. hadoop大数据——mapreduce程序提交运行模式及debug方法

    本地运行模式 (1)mapreduce程序是被提交给LocalJobRunner在本地运行 (2)而处理的数据及输出结果可以在本地文件系统,也可以在hdfs上 怎样实现本地运行?:写一个程序,不要带集 ...

  3. HDFS设计思路,HDFS使用,查看集群状态,HDFS,HDFS上传文件,HDFS下载文件,yarn web管理界面信息查看,运行一个mapreduce程序,mapreduce的demo

    26 集群使用初步 HDFS的设计思路 l 设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l 在大数据系统中作用: 为各类分布式 ...

  4. HDFS设计思路,HDFS使用,查看集群状态,HDFS,HDFS上传文件,HDFS下载文件,yarn web管理界面信息查看,运行一个mapreduce程序,mapreduce的demo...

    26 集群使用初步 HDFS的设计思路 l 设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l 在大数据系统中作用: 为各类分布式 ...

  5. 使用命令行编译打包运行自己的MapReduce程序 Hadoop2.4.1

    网上的MapReduce WordCount教程对于如何编译WordCount.java几乎是一笔带过- 而有写到的,大多又是 0.20 等旧版本版本的做法,即 javac -classpath /u ...

  6. 使用Eclipse编译运行MapReduce程序 Hadoop2.6.0/Ubuntu

    上篇介绍了使用命令行编译打包运行自己的MapReduce程序,使用 Eclipse 更加方便.要在 Eclipse 上编译和运行 MapReduce 程序,需要安装 hadoop-eclipse-pl ...

  7. Hadoop学习全程记录——在Eclipse中运行第一个MapReduce程序

    网友分享,拿来共享一下 这是Hadoop学习全程记录第2篇,在这篇里我将介绍一下如何在Eclipse下写第一个MapReduce程序. 新说明一下我的开发环境: 操作系统:在windows下使用wub ...

  8. Hadoop+eclipse运行MapReduce程序

    前面,我们已经通过eclipse下安装Hadoop的插件配置好了基于Hadoop+eclipse的MapReduce开发环境.现在,我们在这个Hadoop+eclipse环境下运行MapReduce程 ...

  9. IDEA+Maven运行调试MapReduce程序

    IDEA+Maven运行调试MapReduce程序 文章目录 IDEA+Maven运行调试MapReduce程序 新建java类 配置输入文件路径 修改level参数 添加Application配置 ...

最新文章

  1. aix oracle 登录用户,AIX 系统及 Oracle 数据库用户权限管理
  2. linux怎么到conf目录,linux - 如何在没有.conf文件的情况下从Ubuntu下的命令行连接到WiFi? - Ubuntu问答...
  3. 最强蜗牛击败毁灭机器人_最强蜗牛:恶魔形态解锁攻略
  4. webbench源码解析
  5. rn如何测试数据请求时间_rn最新版测试
  6. Linux内核链表的移植与使用
  7. 这就是飞秋下载早期的学习生涯
  8. linux下chkConfig的用法,mysqld开机自启动
  9. php把字符串变成多组,php把字符串变成数组(有分隔符)
  10. Buffer.concat()
  11. C#遍历DataSet数据的几种方法总结
  12. Linux总结篇 linux命令 虚拟机 - (二)
  13. matlab2020面板介绍
  14. 近期几篇有关All-Pay论文总结(博弈论+机制设计)
  15. 辛苦开发的 App 被山寨?mPaaS 帮你为 APK 上把加固锁
  16. 线段树维护(最大区间和,最大子段和,最长连续上升子序列)
  17. 简单聊聊Long Short Term Memory Network (LSTM)和 Gated Recurrent Unit (GRU)两种强大的RNN变体
  18. android 系统源码分析
  19. feded计算机音乐,Romeo And Jazzie/Alan Walker《Faded Refix》[FLAC/MP3-320K]
  20. 百度创始人李彦宏:互联网的下一章

热门文章

  1. bat、sh等批处理文件(脚本文件)
  2. 实验三编程、编译、连接、跟踪
  3. 洛谷 [P1801] 黑匣子
  4. UVA 12034 Race
  5. python操作文件的笔记
  6. 64位虚拟机安装64位ubuntu出现问题
  7. 我的总结SVN的使用
  8. Maven搭建springMVC+spring+hibernate环境
  9. mysql存储过程写法—动态参数运用
  10. Linux下同步工具inotify+rsync使用详解