Hadoop总结之MR

1.思考 MR的缺点?
  1. 不擅长实时计算
    hadoop 的 文件是存储磁盘的 hdfs 内,传输相比内传会慢很多,相比较 Storm 和 Spark 的流处理,流处理不需要批处理的数据收集时间,也省去; 作业调度的时延。
  2. 不擅长流式计算
    流式计算的输入数据是动态的,但是MR 的输入数据集时静态的,不能动态变化。
  3. 不擅长有向图的计算
    多个应用存在依赖关系,后一个程序的输入是前一个的输出。MR 不能进行这样的计算,因为每个 MR 结果都会写入到磁盘,会造成大量的 IO,导致性能非常低下。
2.讲一下MR的工作原理

1) MR 运算程序一般包括两个阶段:Map 阶段和 Reduce 阶段
2)Map 阶段的并发的 MapTask ,完全并行运行,互不相干。
3)Reduce 阶段的并发 ReduceTask ,完全并行运行,互不相干,但是他们的数据依赖于上一阶段的所有MapTask 的并发实例的输出。
4)MR 的编程模型只能包含一个 Map 阶段和 Reduce 阶段,如果用户业务逻辑非常复杂,可以考虑将多个MapReduce 程序穿行运行。
涉及到一些细节问题:

(1)MapTask 的工作机制/如何工作?

在这里插入图片描述
(1)有一个待处理文件,在客户端 summit 之前,获得待处理数据的信息,根据参数配置,形成一个任务分配的规划,包括 job.split ,job.xml, wc.jar 。
(2)提交任务规划信息 给Yarn ,RM 启动 MrAppMaster 根据 切片的个数计算MapTask 的个数。
(3)启动MapTask,MapTask 通过InputFormat 去读文件,默认是按行读取,也可自定义InputFormat 的 RecordReader的 read()方法 去读文件,返回 k,v 键值对。
(4)对读取文件进行业务逻辑的处理,进行 context.write(k,v) ,写到 一个收集器里面OutputCollector,然后写到环形缓冲区内,环形缓冲区默认为 100m,溢写阈值是 80%,底层就是一个数组,后端不断接收数据,前端不断被溢出,当达到 80 % 后,进行溢写,溢写之前先对根据key 对数据进行分区,然后进行分区内排序,并且选择性的进行combine 操作,此时的文件是分区且有序的,溢写过程中如果有其他数据进入,那么由剩余的20%反向写入。
(5)对环形缓冲区溢出的小文件执行 merge(合并),形成分区且分区内有序的大文件(排序算法就是归并排序,相当于在调用一次 combiner 。
(6)所有的MapTask 执行完成以后,MrAppMaster 启动相应的ReduceTask,并告知 Reduce 的数据操作范围(分区信息)。
(7)Reduce 拷贝 map 端输出文件,先拷贝到内存,内存不足,再写入到磁盘,每个 ReduceTask只处理一个分区的数据。
(8)合并文件,归并排序,进入 Reduce 方法。
(9)如果设置了分组操作,进行分组(分组的目的,让两个不相同的对象,通过一个条件让其认为是一个对象,从而进入到一个Reducer 方法中。)
(10)执行用户自定义的Reduce 方法
(11)通过 OutPutFormat 将执行的结果输出到文件中
Shuffle 阶段
shuffle 阶段就是从 maptask 从map()方法输出 kv 对,放到环形缓冲区中-----》 用户掉用Reduce()之前都是属于 Shuffle 阶段。
(1)maptask 收集 map()方法输出的 kv 对,放到收集器,然后进行分区,分区内排序,然后写到环形缓冲区。
(2)当达到环形缓冲区的 80% 时,进行溢写,在溢出过程及合并的过程中,都要掉用 Partitioner 进行分区和针对 key 排序,多个溢出文件会被合并成大的溢出文件。
(3)reducetask 根据自己的分区号,去各个 maptask 机器上去相应的分区数据。
(4)reducetask 会取到同一个分区来自不同 maptask 的结果文件,reducetask 会将这些文件在进行合并(归并排序)。
(5)合并成大文件后,Shuffle 过程结束,后面进入 ReduceTask 的逻辑运算过程。
注意:
shuffle 中缓冲区大小会影响到 mr 程序的执行效率,原则上说,缓冲区越大,溢出文件的次数就越少,磁盘 IO 次数就越少,执行速度就越快,可作为优化 MR的一种方法。
环形缓冲区的大小可以通过参数调整,参数:io.sort.mb 默认 100M。

(2)ReduceTask 的工作机制/如何工作?
(3)MapTask 如何控制分区、排序?
1. 分区,默认的是通过 getPartionner()方法获得。
// 默认分区时根据 键的 hashcode 对 设置的 numReducetasks 求余得到,用户没法控制哪个 key 存在哪个分区
public int getPartition(K key,V value, int numReduceTasks){
	return (key.hashcode() & Interger.MAX_VALUE) % numReduceTasks;
}
2.分区总结
 a. 如果 reducetask 的数量 > getpartition 的结果数,就会多产生几个空的输出文件 part-r-000xx;
 b.如果 reducetask 的数量 < getpartition 的结果数,则一部分数据无处安放,报错。
 c.  reducetask 的数量 = 1 ,不论有几个 reducetask ,最终结果只交给一个reducetask,生成一个输出文件。
 d.分区号必须从 0 开始,逐 1 累加。
(4)MapTask 和 ReduceTask 之间如何衔接?
NodeManager 的 MrAppMaster 启动相应的ReduceTask,并告知 Reduce 的数据
操作范围(分区信息)。 
5.为什么要进行序列化?

一般的“活的”对象只生存在内存里,关机断电就会消失,而且“活的”对象只能由本地的进程使用,不能发送到另一台计算机上。然而序列化可以存储“活的”对象,可以将内存中的对象发送到另一台计算机上。

思考:Hadoop 序列化为什么不用java的序列化?

java 序列化是一个重量级的序列化框架,一个对象序列化后,会带很多额外的信息(各种校验、Header、继承体系),导致对象比较笨重,不能再网络中高效传输,所以 Hadoop 就自己开发了一套序列化机制(Writable)。

6.描述 job 或则说MapReduce程序 提交流程(Job提交流程源码解析)

在这里插入图片描述
(1)waitForCompletion() --》 job.summit()
(2)建立网络连接,connect() : 1.创建 job 实例对象,2.判断是本地\yarn\ 远程.
(3) 创建给集群提交数据的 stag 路径,获取 jobid,拷贝 jar 包到集群(若非集群模式),计算切片,生成切片规划文件 job.split,向 Stag 路径写 XML配置文件。
(4)提交 Job,返回提交状态。

7.FileInputFormat 切片源码解析

流程:
(1)程序先找到你数据存储的目录
(2)开始遍历处理(规划切片)目录下的每一个文件
(3)遍历第一个文件 ss.txt
a) 获取文件大小
b)计算切片大小

		//默认= blocksize = 128M
		computeSplitSize(Math.max(minSize , Math.min(maxSize,blocksize))) 
		

c)开始切,第一个切片 0 - 128M,第二个 128 - 256M ,第三个 256 - 300M
注意:每次切片是,都要判断切完剩下的部分是否大于块的 1.1 倍,不大于 1.1倍就划分成一块切片。
d) 将切片信息写到每一个切片规划文件中。
e)整个切片的核心过程 再 getSplit() 方法中完成。
(4)提交切片规划文件到 YARN 上,YARN 上的 MrAppMaster 就可以根据切片规划文件计算开启的Maptask 个数。

8.排序 WritableComparable
  1. 描述MR哪些过程发生了排序?

  2. 对于maptask ,它 将 map()处理的结果放到环形缓冲区,当环形缓冲区使用率达到一定阈值后,对缓冲区中的数据进行一次快速排序,先分区,然后在分区内排序,并将这些有序数据溢写到磁盘上,而当数据处理完毕后,她对磁盘上的所有文件进行归并排序。

  3. 对于 reducetask, 它从maptask 上远程拷贝相应的数据文件,如果文件大于一定阈值,则 溢写道磁盘上,否则先存放在内存中。如果磁盘文件数目达到一定阈值,则进行一次归并排序 以生成一个更大的文件;如果内存中文件大小或则数目超过一定阈值,则进行一次归并排序后溢写到磁盘上。所有数据拷贝完毕后, reducetask 统一对内存和磁盘上的所有数据进行一次归并排序。

  4. 排序的分类
    (1)部分排序
    Mapreduce 根据输入记录的键对数据集排序,保证输出的每个文件内部有序。
    (2)全排序
    最终输出结果只有一个文件,且文件内部有序。
    (3)辅助排序(GroupingComparator分组)
    在reduce 端对key 进行分组。应用于: 在接收 key 为bean 对象时,想让一个或几个字段相同(全部字段比较不同)的key 进入同一个reduce 方法,采用分组排序。
    (4)二次排序
    在自定义的排序过程中,如果 CompareTo 中判断条件有两个即为 二次排序,比如先按总成绩排序,再按数学成绩排序。

9. Combiner 合并

在这里插入图片描述

10.Map Join

1.使用场景
Map join 适用于一个表十分小(因为可将小表缓存到内存中),一个表很大的场景。
2.优点
可避免在 reduce 端处理过多的表,造成数据倾斜。
在 map 端缓存多张表,提前处理业务逻辑,通过增加map 业务,减少reduce 端数据的压力,尽可能减少数据倾斜。

11 MapReduce总结在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

12.Yarn 资源调度器
  1. Yarn 主要由四部分组成,ResourceManager、NodeManage、ApplicationMaster、Container 等组件组成。
    在这里插入图片描述
  2. Yarn 工作机制
    在这里插入图片描述
    1)MR 程序提交到客户端所在的节点。
    2)YarnRunner 向 RM 申请一个 Application .
  1. RM 将应用程序的资源路径返回给 YarnRunner.(/./.stag,job_id)
    4)该程序将运行所需资源提交到 HFDS 上(job.split、job.xml、wc.jar等放到stag 路径下)。
    5)程序资源提交完毕后,申请运行 MrAppMaster.
    6)RM 将用户请求初始化成一个 task,放到资源调度队列中,等待空闲的节点。
    7)其中一个 NodeManager 领到任务
    8)NM 创建 Container ,并产生 MrAppMaster。
    9)Container 从 HDFS 拷贝资源(stag/)到本地。
    10)MrAppMaster 向 RM 申请MapTask 资源
    11)RM 将运行 MapTask 任务分配给两个 NM,这两个NM 分别领取资源并创建容器。
    12) MR 向两个接收任务的NM发送启动脚本,两个NM 分别启动 MapTask,MapTask 等map ()方法之后,对数据分区排序。
    13)MrAppMaster 等待所有的 MapTask 完成后,向RM申请容器,申请 ReduceTask

  2. ReduceTask 拷贝 MapTask 相应分区的文件。
    15)程序运行完毕后,Mr 向RM申请注销自己。
    资源调度器
    1.FIFO 调度器 :
    按照时间顺序,先到先服务。
    2.Capacity 调度器
    1)支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO策略。
    2)为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源进行限定。
    3)一个 job 放进哪个队列,取决于哪个队列最闲,就是该队列中运行的任务所需的资源比上任务数最大,就说明该队列最闲。
    4)队列内,job 的排序按照体建时间和任务优先级排序。
    3.公平调度器
    按照缺额排序,缺额大者优先。
    公平调度器旨在为所有运行的应用公平分配资源。

    接下来解释资源是如何在队列之间公平共享的。想象两个用户A和B,分别拥有自己的队列。A启动一个作业,在B没有需求时A会分配到全部可用资源;当A的作业仍在运行时B启动一个作业,一段时间后,按照我们先前看到的方式,每个作业都用到了一半的集群资源。这时,如果B启动第二个做作业且其他作业仍在运行,那么第二个作业将和B的其他作业(这里是第一个)共享资源,因此B的每个作业将占四分之一的集群资源,而A仍继续占用一半的集群资源。最终的结果就是资源在用户之间实现了公平共享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值