前言
根据参考的各大面试题进行总结,并且不断更新。希望能帮助大家
一、基础
-
简述hadoop安装
1)使用 root 账户登录
2)修改 IP
3)修改 host 主机名
4)配置 SSH 免密码登录
5)关闭防火墙
6)安装 JDK
7)解压 hadoop 安装包
8)配置 hadoop 的核心文件 hadoop-env.sh,core-site.xml , mapred-site.xml ,hdfs-site.xml
9)配置 hadoop 环境变量
10)格式化 hadoop namenode-format
11)启动节点 start-all.sh -
Hadoop运行模式
单机版、伪分布式模式、完全分布式模式。
单机版: 无需任何守护进程,所有的程序都运行在同一个JVM上执行。在独立模式下调试MR程序非常高效方便。所以一般该模式主要是在学习或者开发阶段调试使用 。
伪分布模式: Hadoop守护进程运行在本地机器上,模拟一个小规模的集群,换句话说,可以配置一台机器的Hadoop集群,伪分布式是完全分布式的一个特例。
完全分布式模式: Hadoop守护进程运行在一个集群上。
注:hadoop 的守护进程
NameNode
DataNode
SecondaryNameNode
ResourceManager
NodeManager -
Hadoop生态圈的组件并做简要描述
1)Zookeeper:是一个开源的分布式应用程序协调服务,基于zookeeper可以实现同步服务,配置维
护,命名服务
2)Flume:一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统
3)Hbase:是一个分布式的、面向列的开源数据库, 利用Hadoop HDFS作为其存储系统
4)Hive:基于Hadoop的一个数据仓库工具,可以将结构化的数据档映射为一张数据库表,并提供简
单的sql 查询功能,可以将sql语句转换为MapReduce任务进行运行
5)Sqoop:将一个关系型数据库中的数据导进到Hadoop的 HDFS中,也可以将HDFS的数据导进到关系型数据库中 -
解释“hadoop”和“hadoop 生态系统”两个概念
hadoop生态系统
hadoop生态系统,不仅包含hadoop,还包括保证zookeeper、Flume、Hbase、Hive、Sqoop等辅助大数据组件。而hadoop单单指hadoop框架本身。 -
Hadoop集群中Hadoop都分别需要启动哪些进程,各自的具体作用?
(1) NameNode
负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。
(2) DataNode
存储文件块数据(也就是存储文件的数据),以及块数据的校验和。
(3) SecondaryNameNode
主要用于定期合并命名空间镜像和命名空间镜像的编辑日志。
(4) nodemanager
管理单个节点上的资源。
(5) ResourceManger
处理客户端请求,监控nodemanager,资源的分配和调度。 -
Hadoop常用端口号
hadoop2.x | Hadoop3.x | |
---|---|---|
访问HDFS端口 | 50070 | 9870 |
访问MR执行情况端口 | 8088 | 8088 |
历史服务器 | 19888 | 19888 |
客户端访问集群端口 | 9000 | 8020 |
-
谈谈 Hadoop 序列化和反序列化及自定义 bean 对象实现序列化?
(1)序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。
(2)反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象。
(3)Java 的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以,hadoop 自己开发了一套序列化机制(Writable),精简、高效。
二、HDFS
-
hdfs的组成架构
架构主要由四个部分组成,分别为HDFS Client、NameNode、DataNode和Secondary NameNode。
(1) Client:就是客户端。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储。
(2) NameNode:就是Master,它是一个主管、管理者。负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。
(3) DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作。存储文件块数据(也就是存储文件的数据),以及块数据的校验和。
(4)Secondary NameNode:辅助NameNode,分担其工作量。定期合并Fsimage和Edits,并推送给NameNode; 在紧急情况下,可辅助恢复NameNode。 -
HDFS 中的 block 默认保存几份?
不管是hadoop1.x 还是hadoop2.x 都是默认的保存三份,可以通过参数dfs.replication就行修改,副本的数目要根据机器的个数来确定。 -
HDFS 默认 BlockSize 是多大?
Hadoop 2.7.2版本及之前默认64MB,Hadoop 2.7.3版本及之后默认128M -
负责HDFS数据存储的是哪一部分?
DataNode负责数据存储. -
namenode的safemode是怎么回事?如何才能退出safemode?
namenode在刚启动的时候元数据只有文件块信息,没有文件所在datanode的信息,需要datanode自己向namenode汇报。如果namenode发现datanode汇报的文件块信息没有达到namenode内存中所有文件块的总阈值的一个百分比,namenode就会处于safemode。 只有达到这个阈值,namenode才会推出safemode。也可手动强制退出。 -
NameNode 与SecondaryNameNode 的区别与联系?
1)机制流程同上;
2)区别
(1)NameNode 负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。
(2)SecondaryNameNode 主要用于定期合并命名空间镜像和命名空间镜像的编辑日志。
3)联系:
(1)SecondaryNameNode 中保存了一份和 namenode 一致的镜像文件(fsimage)和编
辑日志(edits)。
(2)在主 namenode 发生故障时(假设没有及时备份数据),可以从 SecondaryNameNode恢复数据。 -
HDFS的存储机制
HDFS存储机制,包括HDFS的写入数据过程和读取数据过程两部分。
HDFS写数据过程
(1)客户端向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在。
(2)namenode返回是否可以上传。
(3)客户端请求第一个 block上传到哪几个datanode服务器上。
(4)namenode返回3个datanode节点,分别为dn1、dn2、dn3。
(5)客户端请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成
(6)dn1、dn2、dn3逐级应答客户端
(7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答
(8)当一个block传输完成之后,客户端再次请求namenode上传第二个block的服务器。(重复执行3-7步)
HDFS读数据过程
(1) 客户端向namenode请求下载文件,namenode通过查询元数据,找到文件块所在的datanode地址。
(2) 挑选一台datanode(就近原则,然后随机)服务器,请求读取数据。
(3)datanode开始传输数据给客户端(从磁盘里面读取数据放入流,以packet为单位来做校验)。
(4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件。
-
HAnamenode 是如何工作的?
hdfs 是一个分布式文件系统,有namenode和datanode,我们都知道,一旦namenode荡机,整个集群就会瘫痪,那么这个问题怎么处理:一般我们都会有两个namenode,我们知道有一个secondary namenode,但是我们知道这个namenode并不能执行namenode的功能,他只是帮namenode做操作日志的合并,所以我们需要另一种部署模式,即HA部署模式
在高可用集群中有两个namenode,其中一个为active,另一个作standby,active的namenode负责集群中所有的客户端操作,而原来的secondaryNamenode也不需要了,数据交互由轻量级进程journalNode完成,对于任何由主namenode的修改操作,standby的namenode监测到之后会同步journalnode里面的修改log,当active namenode挂了后会读取journalnode里面的修改日志,接替它的位置并保证数据的同步。而namenode的健康状态的判定由zookeeper决定,在每个namenode启动时,会在zookeeper上注册一个持久化节点,而zookeeper提供一个znode(独占锁)获取master的功能,两个namenode谁得到谁就是active状态,另一个保持standby,实际工作中hadoop会提供一个ZKFailoverControl角色在每个主节点周期性的探测namenode的健康状态,当它出问题了独占锁将会给备份的namenode代替原来的主机负责其职责。 -
HDFS的数据压缩算法
Hadoop中常用的压缩算法有bzip2、gzip、lzo、snappy,其中lzo、snappy需要操作系统安装native库才可以支持。
数据压缩的位置如下所示。
MapReduce数据压缩解析
输入端采用压缩
在有大量数据并计划重复处理的情况下,应该考虑对输入进行压缩。然而,你无须显示指定使用的编解码方式。Hadoop自动检查文件扩展名,如果扩展名能够匹配,就会用恰当的编解码方式对文件进行压缩和解压。否则,Hadoop就不会使用任何编解码器。
mapper输出端采用压缩
当map任务输出的中间数据量很大时,应考虑在此阶段采用压缩技术。这能显著改善内部数据Shuffle过程,而Shuffle过程在Hadoop处理过程中是资源消耗最多的环节。如果发现数据量大造成网络传输缓慢,应该考虑使用压缩技术。可用于压缩mapper输出的快速编解码器包括LZO或者Snappy。
reducer输出采用压缩
在此阶段启用压缩技术能够减少要存储的数据量,因此降低所需的磁盘空间。当mapreduce作业形成作业链条时,因为第二个作业的输入也已压缩,所以启用压缩同样有效。
压缩方式对比
(1) Gzip 压缩
优点:压缩率比较高,而且压缩/解压速度也比较快; hadoop 本身支持,在应用中处理gzip 格式的文件就和直接处理文本一样;大部分 linux 系统都自带 gzip 命令,使用方便.
缺点:不支持 split。
应用场景: 当每个文件压缩之后在 130M 以内的(1 个块大小内),都可以考虑用 gzip压缩格式。 例如说一天或者一个小时的日志压缩成一个 gzip 文件,运行 mapreduce 程序的时候通过多个 gzip 文件达到并发。 hive 程序, streaming 程序,和 java 写的 mapreduce 程序完全和文本处理一样,压缩之后原来的程序不需要做任何修改。
(2) Bzip2 压缩
优点:支持 split;具有很高的压缩率,比 gzip 压缩率都高; hadoop 本身支持,但不支持 native;在 linux 系统下自带 bzip2 命令,使用方便。
缺点:压缩/解压速度慢;不支持 native。
应用场景: 适合对速度要求不高,但需要较高的压缩率的时候,可以作为 mapreduce 作业的输出格式; 或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持 split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。
(3) Lzo 压缩
优点:压缩/解压速度也比较快,合理的压缩率;支持 split,是 hadoop 中最流行的压缩格式;可以在 linux 系统下安装 lzop 命令,使用方便。
缺点:压缩率比 gzip 要低一些; hadoop 本身不支持,需要安装;在应用中对 lzo 格式的文件需要做一些特殊处理(为了支持 split 需要建索引,还需要指定 inputformat 为 lzo 格式)。
应用场景: 一个很大的文本文件,压缩之后还大于 200M 以上的可以考虑,而且单个文件越大, lzo 优点越越明显。
(4) Snappy 压缩
优点:高速压缩速度和合理的压缩率。
缺点:不支持 split;压缩率比 gzip 要低; hadoop 本身不支持,需要安装;
应用场景: 当 Mapreduce 作业的 Map 输出的数据比较大的时候,作为 Map 到 Reduce的中间数据的压缩格式;或者作为一个 Mapreduce 作业的输出和另外一个Mapreduce 作业的输入。 -
HDFS 在读取文件的时候,如果其中一个块突然损坏了怎么办
其中⼀个块坏了,只要有其它块存在,会⾃动检测还原。 -
NameNode在启动的时候会做哪些操作?
NameNode启动后,会进入30秒的等待时间,此时处于安全模式。此时NameNode做两件事:
第一件,接受DataNode的心跳和块状态报告,心跳为每3秒发送一次,用来标记是否存活,而块的状态报告主要是用来发送NameNode节点下各个块的状态,默认每一小时发送一次,之后NameNode就会根据自身的元数据来比对DataNode发送的所有块报告的数据是否匹配来判断各个DataNode是否正常。
第二件,NameNode会去加载fsimage镜像文件和edits编辑日志文件,并将其两合并生成一个新的fsimage镜像文件和生成空的edits编辑日志文件。
三、MapReduce
-
mapReduce 中 shuffle 阶段的工作流程?
1)maptask 收集我们的 map()方法输出的 kv 对,放到内存缓冲区中
2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
3)多个溢出文件会被合并成大的溢出文件
4)在溢出过程中,及合并的过程中,都要调用 partitioner 进行分区和针对 key 进行排序
5)reducetask 根据自己的分区号,去各个 maptask 机器上取相应的结果分区数据
6)reducetask 会取到同一个分区的来自不同 maptask 的结果文件,reducetask 会将这些文件再进行合并(归并排序)
7)合并成大文件后,shuffle 的过程也就结束了,后面进入 reducetask 的逻辑运算过程(从文件中取出一个一个的键值对 group,调用用户自定义的 reduce()方法) -
描述mapReduce中combiner和partition的作用
combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量 partition的默认实现是hashpartition,是map端将数据按照reduce个数取余,进行分区,不同的reduce来copy自己的数据。 partition的作用是将数据分到不同的reduce进行计算,加快计算效果。 -
如果没有定义partitioner,那数据在被送达reducer前是如何被分区的?
如果没有自定义的partitioning,则默认的partition算法,即根据每一条数据的key的hashcode值模运算(%)reduce的数量,得到的数字就是“分区号“。 -
FileInputFormat切片机制
job提交流程源码详解
waitForCompletion()
submit();
// 1、建立连接
connect();
// 1)创建提交job的代理
new Cluster(getConfiguration());
// (1)判断是本地yarn还是远程
initialize(jobTrackAddr, conf);
// 2、提交job
submitter.submitJobInternal(Job.this, cluster)
// 1)创建给集群提交数据的Stag路径
Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf);
// 2)获取jobid ,并创建job路径
JobID jobId = submitClient.getNewJobID();
// 3)拷贝jar包到集群
copyAndConfigureFiles(job, submitJobDir);
rUploader.uploadFiles(job, jobSubmitDir);
// 4)计算切片,生成切片规划文件
writeSplits(job, submitJobDir);
maps = writeNewSplits(job, jobSubmitDir);
input.getSplits(job);
// 5)向Stag路径写xml配置文件
writeConf(conf, submitJobFile);
conf.writeXml(out);
// 6)提交job,返回提交状态
status = submitClient.submitJob(jobId, submitJobDir.toString(),
job.getCredentials());
-
在一个运行的Hadoop 任务中,什么是InputSplit?
FileInputFormat源码解析(input.getSplits(job))
1)找到你数据存储的目录
2)开始遍历处理(规划切片)目录下的每一个文件
3)遍历第一个文件(假设为ss.txt)
(1)获取文件大小fs.sizeOf(ss.txt);
(2)计算切片大小
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
(3)默认情况下,切片大小=blocksize
(4)开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss
256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切
片)
(5)将切片信息写到一个切片规划文件中
(6)整个切片的核心过程在getSplit()方法中完成。
(7)数据切片只是在逻辑上对输入数据进行分片,并不会再磁盘上将其切分成分片进行存储
InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等。
(8)注意:block是HDFS上物理上存储的存储的数据,切片是对数据逻辑上的划分。
4) 提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启maptask
个数。 -
如何判定一个job的map和reduce的数量?
1)map数量
map数量由处理的数据分成的block数量决定default_num = total_size / split_size;
2)reduce数量
reduce的数量job.setNumReduceTasks(x);x 为reduce的数量。不设置的话默认为 1 -
Maptask的个数由什么决定?
一个job的map阶段MapTask并行度(个数),由客户端提交job时的切片个数决定。 -
描述mapReduce有几种排序及排序发生的阶段
1)排序的分类:
(1)部分排序:
MapReduce 根据输入记录的键对数据集排序。保证输出的每个文件内部排序。
(2)全排序:
如何用 Hadoop 产生一个全局排序的文件?最简单的方法是使用一个分区。但该方法在
处理大型文件时效率极低,因为一台机器必须处理所有输出文件,从而完全丧失了
MapReduce 所提供的并行架构。
替代方案:首先创建一系列排好序的文件;其次,串联这些文件;最后,生成一个全局
排序的文件。主要思路是使用一个分区来描述输出的全局排序。例如:可以为待分析文件创
建 3 个分区,在第一分区中,记录的单词首字母 a-g,第二分区记录单词首字母 h-n, 第三分
区记录单词首字母 o-z。
(3)辅助排序:(GroupingComparator 分组)
Mapreduce 框架在记录到达 reducer 之前按键对记录排序,但键所对应的值并没有被排
序。甚至在不同的执行轮次中,这些值的排序也不固定,因为它们来自不同的 map 任务且
这些 map 任务在不同轮次中完成时间各不相同。一般来说,大多数 MapReduce 程序会避免
让 reduce 函数依赖于值的排序。但是,有时也需要通过特定的方法对键进行排序和分组等
以实现对值的排序。
(4)二次排序:
在自定义排序过程中,如果 compareTo 中的判断条件为两个即为二次排序。
2)自定义排序 WritableComparable
bean 对象实现 WritableComparable 接口重写 compareTo 方法,就可以实现排序。 -
如何使用mapReduce实现两个表的join?
reduce side join:
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条
数据打一个标签(tag),比如:tag=0 表示来自文件File1,tag=2 表示来自文件File2。
Map side join:
Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以
至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task 内存中存在一份
(比如存放到hash table 中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table
中查找是否有相同的key 的记录,如果有,则连接后输出即可。 -
MapReduce程序运行流程
MapReduce程序的执行过程分为两个阶段:Mapper阶段和Reducer阶段。
其中Mapper阶段可以分为6个步骤:
第一阶段:先将HDFS中的输入文件file按照一定的标准进行切片,默认切片的类为FileInputFormat,通过切片输入文件将会变成split1、split2、split3……;随后对输入切片split按照一定的规则解析成键值对<k1,v1>,默认处理的类为TextInputFormat。其中k1就是我们常说的起始偏移量,v1就是行文本的内容。
第二阶段:调用自己编写的map逻辑,将输入的键值对<k1,v1>变成<k2,v2>。在这里要注意:每一个键值对<k1,v1>都会调用一次map函数。
第三阶段:按照一定的规则对输出的键值对<k2,v2>进行分区:分区的规则是针对k2进行的,比如说k2如果是省份的话,那么就可以按照不同的省份进行分区,同一个省份的k2划分到一个区。注意:默认分区的类是HashPartitioner类,这个类默认只分为一个区,因此Reducer任务的数量默认也是1.
注意:如reduce要求得到的是全局的结果,则不适合分区!
第四阶段:对每个分区中的键值对进行排序。注意:所谓排序是针对k2进行的,v2是不参与排序的,如果要让v2也参与排序,需要自定义排序的类,具体过程可以参看博主文章。
第五阶段:排序完之后要进行分组,即相同key的value放到同一个集合当中,例如在WordCount程序中的<hello,{1,1}>执行的就是这个步骤,但是要注意:分组也是针对key进行的,经过分组完之后,就得到了我们熟悉的键值对<k2,v2s>.
第六阶段(可选):对分组后的数据进行归约处理。通过归约处理键值对<k2,v2s>变成了<k2,v2>,经过这一阶段,传送到Reducer任务端的数据量会减少。但是规约的使用是有条件的,所以这一阶段是可以选择的。
Mapper任务处理完之后,就进入到了我们的Reducer阶段:
Reducer任务的执行过程可以分为3个阶段:
第一阶段:对多个Mapper任务的输出,按照不同的分区,通过网络拷贝到不同的Reducer节点上进行处理,将数据按照分区拷贝到不同的Reducer节点之后,对多个Mapper任务的输出在进行合并,排序。例如:在WordCount程序中,若一个Mapper任务输出了<hello,{1,1}>,另外一个Mapper任务的输出为<hello,{1,1,1}>,经过在次合并之后变为<hello,{1,1,1,1,1}>.
第二阶段:调用自己的reduce逻辑,将键值对<k2,v2s>变为<k3,v3>.在这里注意:每一个键值对<k2,v2s>都会调用一次reduce函数。
第三阶段:将Reducer任务的输出保存到指定的文件中。
经过上面的具体分析之后,我们在通过WordCount业务进行具体的说明,假设输入文件的内容为:
在这里我们通过第一条记录“helloyou”进行具体的说明MapReduce程序的执行过程,注:默认一个分区,整个过程处理如下:
到此,MapReduce程序的流程大致就讲述完了,其实从宏观上来看,无非就是对键值的不断处理。 -
用mapreduce怎么处理数据倾斜问题?
数据倾斜:map /reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长, 这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多, 从而导致某几个节点迟迟运行不完,此称之为数据倾斜。
解决:自己实现partition类,用key和value相加取hash值。
数据的倾斜主要是两个的数据相差的数量不在一个级别上,在只想任务时就造成了数据的倾斜,可以通过分区的方法减少reduce数据倾斜性能的方法。 -
什么样的计算不能用mr来提速?
1)数据量很小。
2)繁杂的小文件。
3)索引是更好的存取机制的时候。
4)事务处理。
5)只有一台机器的时候。
四、YARN
- 简单概述一下hadoop1与hadoop2的区别
Hadoop2与hadoop1最大的区别在于HDFS的架构与mapreduce的很大的区别,而且速度上有很大的提升,hadoop2最主要的两个变化是:namenode可以集群的部署了,hadoop2中的mapreduce中的jobTracker中的资源调度器与生命周期管理拆分成两个独立的组件,并命名为YARN 。 - Hadoop的调度器总结
Hadoop作业调度器主要有三种:FIFO、Capacity Scheduler和Fair Scheduler。Hadoop3.1.3默认的资源调度器是Capacity Scheduler。CDH 版本的默认使用的是 fair scheduler 调度方式
具体设置详见:yarn-default.xml文件
1)先进先出调度器(FIFO)
FIFO Scheduler 把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给 下一个分配,以此类推。FIFO Scheduler 是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞。在共享集群中,更适合采用 Capacity Scheduler 或 Fair Scheduler,这两个调度器都允许大任务和小任务在提交的同时获得一定的系统资源。
2)容量调度器(Capacity Scheduler)
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
3)公平调度器(Fair Scheduler)
Fair 调度器会为所有运行的 Job 动态的调整系统资源。当第一个大 job 提交时,只有这一个 job 在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair 调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。需要注意的是,在上图 Fair 调度器中,从第二个任务提交到获得资源会有一定的延迟,因为它需要等待第一个任务释放占用的 Container。小任务执行完成之后也会释放自己占用的资源,大任务又获得了全部的系统资源。最终效果就是 Fair 调度器即得到了高的资源利用率又能保证小任务及时完成。 - yarn工作流程
运行流程
1、客户端向RM中提交程序
2、RM向NM中分配一个container,并在该container中启动AM
3、AM向RM注册,这样用户可以直接通过RM査看应用程序的运行状态(然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束)
4、AM采用轮询的方式通过RPC协议向RM申请和领取资源,资源的协调通过异步完成
5、AM申请到资源后,便与对应的NM通信,要求它启动任务
6、NM为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务
7、各个任务通过某个RPC协议向AM汇报自己的状态和进度,以让AM随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务
8、应用程序运行完成后,AM向RM注销并关闭自己
五、优化问题
-
MapReduce跑得慢的原因
Mapreduce 程序效率的瓶颈在于两点:
1)计算机性能
CPU、内存、磁盘健康、网络
2)I/O 操作优化
(1)数据倾斜
(2)map和reduce数设置不合理
(3)reduce等待过久
(4)小文件过多
(5)大量的不可分块的超大文件
(6)spill次数过多
(7)merge次数过多等。 -
MapReduce优化方法
数据输入阶段
1)合并小文件:在执行mr任务前将小文件进行合并,大量的小文件会产生大量的map任务,增大map
任务装载次数,而任务的装载比较耗时,从而导致 mr 运行较慢。
2)采用ConbinFileInputFormat来作为输入,解决输入端大量小文件场景。
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。
reduce阶段
1)合理设置map和reduce数:两个都不能设置太少,也不能设置太多。太少,会导致task等待,延长处理时间;太多,会导致 map、reduce任务间竞争资源,造成处理超时等错误。
2)设置map、reduce共存:调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间。
3)规避使用reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
4)合理设置reduce端的buffer,默认情况下,数据达到一个阈值的时候,buffer中的数据就会写入磁盘,然后reduce会从磁盘中获得所有的数据。也就是说,buffer和reduce是没有直接关联的,中间多个一个写磁盘->读磁盘的过程,既然有这个弊端,那么就可以通过参数来配置,使得buffer中的一部分数
据可以直接输送到reduce,从而减少IO开销:mapred.job.reduce.input.buffer.percent,默认为0.0。
当值大于0的时候,会保留指定比例的内存读buffer中的数据直接拿给reduce使用。这样一来,设置buffer需要内存,读取数据需要内存,reduce计算也要内存,所以要根据作业的运行情况进行调整。
IO传输
1)采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
2)使用SequenceFile二进制文件
数据倾斜问题
1)数据倾斜现象
数据频率倾斜——某一个区域的数据量要远远大于其他区域。
数据大小倾斜——部分记录的大小远远大于平均值。
2)减少数据倾斜的方法
方法1:抽样和范围分区
可以通过对原始数据进行抽样得到的结果集来预设分区边界值。
方法2:自定义分区
另一个抽样和范围分区的替代方案是基于输出键的背景知识进行自定义分区。例如,如果map输出键
的单词来源于一本书。其中大部分必然是省略词(stopword)。那么就可以将自定义分区将这部分省
略词发送给固定的一部分reduce实例。而将其他的都发送给剩余的reduce实例。
方法3:Combine
使用Combine可以大量地减小数据频率倾斜和数据大小倾斜。在可能的情况下,combine的目的就是聚合并精简数据。 -
HDFS小文件优化方法
1)HDFS 小文件弊端:
HDFS 上每个文件都要在 namenode 上建立一个索引,这个索引的大小约为 150byte,这样当小文件比较多的时候,就会产生很多的索引文件,一方面会大量占用 namenode 的内存空间,另一方面就是索引文件过大是的索引速度变慢。
2)解决的方式:
(1)Hadoop 本身提供了一些文件压缩的方案。
(2)从系统层面改变现有 HDFS 存在的问题,其实主要还是小文件的合并,然后建立比较快速的索引。
总结
持续更新(修改)…