hadoop_5 : Hadoop的机制

  • 4个独立的实体
* 客户端: 提交MapReduce作业
* jobtracker:协调作业的运行
* tasktracker:运行作业划分后的任务
* 分布式文件系统

hadoop_5 : Hadoop的机制_第1张图片

A…… 提交作业:runjob

* runjob()每秒轮询作业进度

B…… JobClient的submitjob方法过程

* 向jobtracker提交请求,得到作业ID(步骤2)
* 检查作业的输出
* 计算作业的输入分片
* 将运行作业的所需资源(作业jar文件,配置文件和计算所得的输入分片)复制到作业ID命名目录下的jobtracker文件。
* 通知jobtracker作业准备执行(步骤4)

C…… 作业的初始化

* jobtracker接收到对其submitjob()方法的调用后,会把此调用放入内部队列,交给作业调度器(job scheduler), 并初始化(步骤5)
* 为创建任务运行列表,作业调度器首先从共享文件系统中获取JobClient已计算好的输入任务分片(步骤6)
* 为每个分片创建map
* 创建的reduce任务的数量由JobConf的mapred.reduce.task 属性决定;
* 任务此时被指定 ID

D…… 任务的分配

* tasktracker运行循环定期发送"心跳"给jobtracker:通知是否tasktracker还活着(步骤7)
* jobtracker为tasktracker选择任务,维护一个作业优先级表
* tasktracker具有固定数量的任务槽:一个tasktracker可以运行的map和reduce数量由tasktracker的核的数量和内存决定
* map任务会选择距离输入最近的tasktracker

E…… 任务的执行

* 从共享文件系统把作业的jar文件复制到tasktracker的文件系统
* jar的本地化
* tasktracker为任务创建一个本地目录,把jar文件的内容解压到文件夹
* tasktracker新建一个taskrunner实例来运行内容
* 启动JVM(步骤9)
* 运行步骤10(maptask或者是reducetask)

F……streaming和Pipes

G……进度和状态的更新

H…… 作业的完成

* 作业状态设置为成功
* runjob()返回

作业的调度

  • 早期采用FIFO
  • 可以设置Hadoop的调度器
* FIFO调度器
* Fair Schedular 调度器:每个用户公平的使用集群
* Capacity Schedular 调度器:集群由多队列组成

shuffle和排序

http://langyu.iteye.com/blog/992916

  • shuffle:将map的输出作为输入传递给reduce的过程

hadoop_5 : Hadoop的机制_第2张图片

* shuffle的期望功能
1. 完整地从map task端拉取数据到reduce 端。
2. 在跨节点拉取数据时,尽可能地减少对带宽的不必要消耗。
3. 减少磁盘IO对task执行的影响。 ---------

* 减少拉取数据的量及尽量使用内存而不是磁盘

Map端(8个map,3个reduce)

hadoop_5 : Hadoop的机制_第3张图片

  • map的输出不是直接写入磁盘:缓存的方式写入内存,并预排序

  • 每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘,当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。

  • Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。

1. 数据源自HDFS的block,mapreduce的split和block是多对一或者一对一,默认一对一

2. 划分(paritition) 
a...MapReduce提供Partitioner接口,它的作用就是根据key或value及reduce的数量来决定当前的这对输出数据最终应该交由哪个reduce task处理。

b...默认对key hash后再以reduce task数量取模。默认的取模方式只是为了平均reduce的处理能力,如果用户自己对Partitioner有需求,可以订制并设置到job上。 

c....key/value对以及Partition的结果都会被写入缓冲区

3.  分割(spill):sort(排序)和combine
a...这个内存缓冲区是有大小限制的,默认是100MB。从内存往磁盘写数据的过程被称为Spill,中文可译为溢写,这个溢写是由单独线程来完成,不影响往缓冲区写map结果的线程(80%)。

b... 当溢写线程启动后,需要对这80MB空间内的key做排序(Sort)。排序是MapReduce模型默认的行为,这里的排序也是对序列化的字节做的排序。 

C... combine:将有相同key的key/value对的value加起来,减少溢写到磁盘的数据量。

4.  Merge on disk
溢写文件归并到一起,这个过程就叫做Merge(对于不同的reduce)
  • map端的所有工作都已结束,最终生成的这个文件也存放在TaskTracker够得着的某个本地目录内。
  • 每个reduce task不断地通过RPC从JobTracker那里获取map task是否完成的信息,如果reduce task得到通知,获知某台TaskTracker上的map task执行完成,Shuffle的后半段过程开始启动。

reduce

  • reduce task在执行之前的工作就是不断地拉取当前job里每个map task的最终结果,然后对从不同地方拉取过来的数据不断地做merge,也最终形成一个文件作为reduce task的输入文件。见下图:

hadoop_5 : Hadoop的机制_第4张图片

  • Reducer真正运行之前,所有的时间都是在拉取数据,做merge,且不断重复地在做。
1. Copy过程,简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求map task所在的TaskTracker获取map task的输出文件。因为map task早已结束,这些文件就归TaskTracker管理在本地磁盘中。  2.        Merge阶段。这里的merge如map端的merge动作,只是数组中存放的是不同mapcopy来的数值。Copy过来的数据会先放入内存缓冲区中,这里的缓冲区大小要比map端的更为灵活,它基于JVM的heap size设置,因为Shuffle阶段Reducer不运行,所以应该把绝大部分的内存都给Shuffle用。这里需要强调的是,merge有三种形式:1)内存到内存  2)内存到磁盘  3)磁盘到磁盘。默认情况下第一种形式不启用,让人比较困惑,是吧。当内存中的数据量到达一定阈值,就启动内存到磁盘的merge。与map 端类似,这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。第二种merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的那个文件。 
 3.        Reducer的输入文件。不断地merge后,最后会生成一个“最终文件”。为什么加引号?因为这个文件可能存在于磁盘上,也可能存在于内存中。对我们来说,当然希望它存放于内存中,直接作为Reducer的输入,但默认情况下,这个文件是存放于磁盘中的。至于怎样才能让这个文件出现在内存中,之后的性能优化篇我再说。当Reducer的输入文件已定,整个Shuffle才最终结束。然后就是Reducer执行,把结果放到HDFS上。 

配置调优

你可能感兴趣的:(hadoop_5 : Hadoop的机制)