Hadoop总结
一、入门
1、简要描述如何安装配置apache的一个开源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,hadfs-site.xml,yarn-site.xml
9)配置Hadoop环境变量
10)格式化hadoop namenode-format
11)启动节点start-all.sh
2、Hadoop中需要哪些配置文件,其作用是什么?
1)core-site.xml
(1)fs.defaultFS:hdfs://cluster(域名),这里的值指的是默认的hdfs路径
(2)hadoop.tmp.dir:/export/data/hadoop tmp 这里的路径默认的是namenode.datanode,secondarynamenode等存放数据的公共目录。用户也可以自己单独指定这三类节点的目录
(3)ha.zookeeper.quorum:hadoop101:2181,hadoop102:2181,hadoop103:2181
这里的zookeeper集群的地址和端口。注意:数量一定是奇数,且不少于三个节点
2)hadoop-env.sh 只需配置jdk的安装路径
3)hdfs-site.xml
(1)dfs.replication:决定着系统里面的文件块数据的备份个数,默认为三个
(2)dfs.data.dir:datanode 节点存储在文件系统的目录
(3)dfs.name.dir是namenode节点存储hadoop文件系统信息的本地系统路径
4)mapred-site.xml
mapreduc.fiamework.name:yarn指定在mr运行在yarn上
5)yarn-site.xml
3、请列出正常工作中Hadoop集群中Hadoop都分别需要启动那些进程,作用分别是什么?
a) NameNode它是hadoop中的主服务器,管理文件系统名称空间和对集群中存储的文件的访问,保存有 metadate.
b).SecondaryNameNode它不是namenode的冗余守护进程,而是提供周期检查点和清理任务。帮助NN合并editslog,减少NN启动时间。
c)DataNode它负责管理连接到节点的存储(一个集群中可以有多个节点)。每个存储数据的节点运行一个datanode守护进程。
d)ResourceManager(JobTracker)JobTracker负责调度DataNode上的工作。每个DataNode有一个TaskTracker,它们执行实际工作。
e) NodeManager(TaskTracker)执行任务
f) DFSZKFailoverController高可用时它负责监控NN的状态,并及时的把状态信息写入ZK。它通过一个独立线程周期性的调用NN上的一个特定接口来获取NN的健康状态。FC也有选择谁作为Active NN的权利,因为最多只有两个节点,目前选择策略还比较简单(先到先得,轮换)。
g) JournalNode 高可用情况下存放namenode的editlog文件.
4、简述Hadoop的几个默认端口号机器含义
1 ) dfs.namenode.http-address:50070
2 ) SecondaryNameNode 辅助名称节点端口号: 50090
3 ) dfs.datanode.address:50010
4 ) fs.defaultFS:8020 或者 9000
5 ) yarn.resourcemanager.webapp.address:8088
hadoop3.x
HDFS NameNode 内部通常端口:8020/9000/9820
HDFS NameNode 对用户的查询端口:9870
Yarn查看任务运行情况的:8088
历史服务器:19888
hadoop2.x
HDFS NameNode 内部通常端口:8020/9000
HDFS NameNode 对用户的查询端口:50070
Yarn查看任务运行情况的:8088
5、 Hadoop的****组成**
Hadoop 1只有两个部分,HDFS和MapReduce,Hadoop 2增加了Yarn用来管理资源调度。具体来说:
HDFS组成:
(1)Namenode:存储文件的元数据以及每个文件的块列表和块所在的DataNode等。
(2)DataNode:在本地文件系统存储文件块数据以及块数据的校验和。
(3)Secondary NameNode:监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。
Yarn组成:
(1)ResorceManager:处理客户端请求,监控NodeManager,启动或监控ApplicationMaster
(2)NodeManager:管理单个节点的资源,处理来自ResourceManager和ApplicationMaster的命令
(3)ApplicationMaster:负责数据的切分,为应用程序申请资源并分配给内部任务,任务的监控与容错
(4)Container:是资源抽象,封装了某个节点的多维度资源,如内存、CPU、磁盘、网络等。
二、HDFS
1、hdfs的存储机制(读写流程)
hhdfs存储机制,包括hdfs的写入过程和读取过程两个部分
HDFS 写数据流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCntVvwR-1623747121399)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210605205903367.png)]
(1)客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,NameNode 检查目标文件是否已存在,父目 录是否存在。
(2)NameNode 返回是否可以上传。
(3)客户端请求第一个 Block 上传到哪几个 DataNode 服务器上。
(4)NameNode 返回 3 个 DataNode 节点,分别为 dn1、dn2、dn3。
(5)客户端通过 FSDataOutputStream 模块请求 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 读数据流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7OpFGVlU-1623747121403)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210605210129072.png)]
(1)客户端通过 DistributedFileSystem 向 NameNode 请求下载文件,NameNode 通过查询元数据,找到文件块所在的 DataNode 地址。
(2)挑选一台 DataNode(就近原则,然后随机)服务器,请求读取数据。
(3)DataNode 开始传输数据给客户端(从磁盘里面读取数据输入流,以 Packet 为单位来做校验)。
(4)客户端以 Packet 为单位接收,先在本地缓存,然后写入目标文件
2、SecondaryNameNode工作机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8RpMyoCP-1623747121406)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210605210915805.png)]
\1. 第一阶段:NameNode启动
(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
(2)客户端对元数据进行增删改的请求。
(3)NameNode记录操作日志,更新滚动日志。
(4)NameNode在内存中对元数据进行增删改。
\2. 第二阶段:Secondary NameNode工作
(1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
(2)Secondary NameNode请求执行CheckPoint。
(3)NameNode滚动正在写的Edits日志。
(4)将滚动前的编辑日志和镜像文件拷贝到SecondaryNameNode。
(5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
(6)生成新的镜像文件fsimage.chkpoint。
(7)拷贝fsimage.chkpoint到NameNode。
(8)NameNode将fsimage.chkpoint重新命名成fsimage
3、NameNode 和 SecondaryNameNode区别和联系
区别:
NameNode负责管理元数据和文件信息
SecondaryNameNode主要用于定期合并Fsimage 和Edits
联系:
SecondaryNameNode中保存了一份和Namenode一致的Fsimage 和Edits 。在Namenode发生故障时,可以从SecondaryNameNode恢复数据,虽然已经不是最新的 Fsimage (SecondaryNameNode从 NameNode 下载 fsimage 和 Edits 文件的时候,新的更新操作已经写到 edit.new 文件中去了) ,但是我们可以将损失减小到最少。
Edits 日志文件存放的是HDFS所有的更改操作日志。
Fsimage 有最新的元数据和HDFS的文件和目录信息,但不包含文件块位置信息,文件块位置信息只存储在内存中。
每个NameNode启动的时候会将Fsimage和Edits 进行合并,保证内存中的元数据是最新的。当客户端对 HDFS 中的文件进行操作时,操作记录首先被记入 Edits 日志文件中,当客户端操作成功后,元数据会更新到内存。每达到触发条件,会由 SecondaryNameNode 将 NameNode 上积累的所有 Edits 和一个最新的 Fsimage 下载到本地,并加载到内存进行合并,生成一个新的 Fsimage 文件并复制到 NameNode 。
4、服役新数据节点和退役节点步骤
1)节点上线操作:
当要新上线数据节点的时候,需要把数据节点的名字追加在 dfs.hosts 文件中
(1)关闭新增节点的防火墙
(2)在 NameNode 节点的 hosts 文件中加入新增数据节点的 hostname
(3)在每个新增数据节点的 hosts 文件中加入 NameNode 的 hostname
(4)在 NameNode 节点上增加新增节点的 SSH 免密码登录的操作
(5)在 NameNode 节点上的 dfs.hosts 中追加上新增节点的 hostname,
(6)在其他节点上执行刷新操作:hdfs dfsadmin -refreshNodes
(7)在 NameNode 节点上,更改 slaves 文件,将要上线的数据节点 hostname 追加到 slaves 文件中
(8)启动 DataNode 节点
(9)查看 NameNode 的监控页面看是否有新增加的节点
2)节点下线操作:
(1)修改/conf/hdfs-site.xml 文件
(2)确定需要下线的机器,dfs.osts.exclude 文件中配置好需要下架的机器,这个是阻止下架的机器去连接 NameNode。
(3)配置完成之后进行配置的刷新操作./bin/hadoop dfsadmin -refreshNodes,这个操作的作用是在后台进行 block 块的移动。
(4)当执行三的命令完成之后,需要下架的机器就可以关闭了,可以查看现在集群上连接的节点,正在执行 Decommission,会显示:Decommission Status : Decommission in progress 执行完毕后,会显示:Decommission Status : Decommissioned
(5)机器下线完毕,将他们从excludes 文件中移除。
5、namenode挂了怎么办?
NameNode故障后,可以通过下列两种方式进行恢复数据:
方法一(手动):将SecondaryNameNode文件下的数据复制到NameNode中
方法二(程序):使用-importCheckpoint选项启动NameNode的守护线程,从而将SecondaryNameNode文件目录下的数 据拷贝到NamenNode中
模拟NameNode故障,并采用方法一,恢复NameNode的数据。
(1)kill -9 NameNode进程
(2)删除NameNode存储的数据($HADOOP_PATH/data/tmp/dfs/name)
$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
(3)拷贝SecondaryNameNode中的数据到原NameNode存储数据目录中
$ scp -r upuptop@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/* ./name/
(4)重启NameNode
$ sbin/hadoop-daemon.sh start namenode
三、MapReduce
1、谈谈Hadoop序列化和反序列化以及自定义bean对象实现序列化
1)序列化和反序列化 :
(1)序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。
(2)反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象。
(3)Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以,hadoop自己开发了一套序列化机制(Writable),精简、高效。
2)自定义bean对象要想序列化传输步骤及注意事项:
(1)必须实现Writable接口
(2)反序列化时,需要反射调用空参构造函数,所以必须有空参构造
(3)重写序列化方法
(4)重写反序列化方法
(5)注意反序列化的顺序和序列化的顺序完全一致
(6)要想把结果显示在文件中,需要重写toString(),且用"\t"分开,方便后续用
(7)如果需要将自定义的bean放在key中传输,则还需要实现comparable接口,因为mapreduce框中的shuffle过程一定会对key进行排序
2、FileInputFormat切片机制
1**)**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());
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pVooiK8u-1623747121410)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606153919548.png)]
3、自定义InputFormat流程
(1)自定义一个类继承FileInputFormat
(2)改写RecordReader,实现一个读取一个完整文件封装为kv
4、如何决定一个job的map和reduce的数量
一、影响map个数,即split个数的因素主要有:
1)HDFS块的大小,即HDFS中dfs.block.size的值。如果有一个输入文件为1024m,当块为256m时,会被划分为4个split;当块为128m时,会被划分为8个split。
2)文件的大小。当块为128m时,如果输入文件为128m,会被划分为1个split;当块为256m,会被划分为2个split。
3)文件的个数。FileInputFormat按照文件分割split,并且只会分割大文件,即那些大小超过HDFS块的大小的文件。如果HDFS中dfs.block.size设置为64m,而输入的目录中文件有100个,则划分后的split个数至少为100个。
4)splitsize的大小。分片是按照splitszie的大小进行分割的,一个split的大小在没有设置的情况下,默认等于hdfs block的大小。但应用程序可以通过两个参数来对splitsize进行调节。
map个数的计算公式如下:
splitsize=max(minimumsize,min(maximumsize,blocksize))。
如果没有设置minimumsize和maximumsize,splitsize的大小默认等于blocksize
二、reduce数量
reduce的数量是job.setNumReduceTasks(x); x为reduce的数量。不设置的话默认为1
5、Maptask的个数有什么决定
一个job的map阶段=MapTask并行度(个数); 由客户端提交job时的切片个数决定
6、MapTask工作机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9omfkmWq-1623747121412)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606155408695.png)]
(1)Read 阶段:MapTask 通过 InputFormat 获得的 RecordReader,从输入 InputSplit 中
解析出一个个 key/value。
(2)Map 阶段:该节点主要是将解析出的 key/value 交给用户编写 map()函数处理,并
产生一系列新的 key/value。
(3)Collect 收集阶段:在用户编写 map()函数中,当数据处理完成后,一般会调用
OutputCollector.collect()输出结果。在该函数内部,它会将生成的 key/value 分区(调用
Partitioner),并写入一个环形内存缓冲区中。
(4)Spill 阶段:即“溢写”,当环形缓冲区满后,MapReduce 会将数据写到本地磁盘上,
生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排
序,并在必要时对数据进行合并、压缩等操作。
溢写阶段详情:
步骤 1:利用快速排序算法对缓存区内的数据进行排序,排序方式是,先按照分区编号
Partition 进行排序,然后按照 key 进行排序。这样,经过排序后,数据以分区为单位聚集在
一起,且同一分区内所有数据按照 key 有序。
步骤 2:按照分区编号由小到大依次将每个分区中的数据写入任务工作目录下的临时文
件
output/spillN.out(N 表示当前溢写次数)中。如果用户设置了 Combiner,则写入文件之
前,对每个分区中的数据进行一次聚集操作。
步骤 3:将分区数据的元信息写到内存索引数据结构 SpillRecord 中,其中每个分区的元
信息包括在临时文件中的偏移量、压缩前数据大小和压缩后数据大小。如果当前内存索引大
小超过 1MB,则将内存索引写到文件 output/spillN.out.index 中。
(5)Merge 阶段:当所有数据处理完成后,MapTask 对所有临时文件进行一次合并,
以确保最终只会生成一个数据文件。
当所有数据处理完后,MapTask 会将所有临时文件合并成一个大文件,并保存到文件
output/file.out 中,同时生成相应的索引文件 output/file.out.index。
在进行文件合并过程中,MapTask 以分区为单位进行合并。对于某个分区,它将采用多
轮递归合并的方式。每轮合并 mapreduce.task.io.sort.factor(默认 10)个文件,并将产生的文
件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。
让每个 MapTask 最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量
小文件产生的随机读取带来的开销。
7、ReducedTask工作机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nPFLsYMZ-1623747121414)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606155635718.png)]
(1)Copy 阶段:ReduceTask 从各个 MapTask 上远程拷贝一片数据,并针对某一片数
据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。
(2)Sort 阶段:在远程拷贝数据的同时,ReduceTask 启动了两个后台线程对内存和磁
盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。按照 MapReduce 语义,用
户编写 reduce()函数输入数据是按 key 进行聚集的一组数据。为了将 key 相同的数据聚在一
起,Hadoop 采用了基于排序的策略。由于各个 MapTask 已经实现对自己的处理结果进行了
局部排序,因此,ReduceTask 只需对所有数据进行一次归并排序即可。
(3)Reduce 阶段:reduce()函数将计算结果写到 HDFS 上。
8、请描述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方法,就可以实现排序
发生阶段有两个
(1)一个是在map side发生在spill后partition前。
(2)一个是在reduce side发生在copy后 reduce前。
二次排序、全排序、部分排序发生在map阶段
辅助排序发生在reduce阶段
9、请描述mapReduce中shuffle阶段的工作流程,如何优化shuffle阶段?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaYoUZwt-1623747121415)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606160909425.png)]
1)Map阶段:
(1)增大环形缓冲区大小。由100m扩大到200m
(2)增大环形缓冲区溢写的比例。由80%扩大到90%
(3)减少对溢写文件的merge次数。(10个文件,一次20个merge)
(4)不影响实际业务的前提下,采用Combiner提前合并,减少 I/O。
2)Reduce阶段:
(1)合理设置Map和Reduce数:两个都不能设置太少,也不能设置太多。太少,会导致Task等待,延长处理时间;太多,会导致 Map、Reduce任务间竞争资源,造成处理超时等错误。
(2)设置Map、Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间。
(3)规避使用Reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
(4)增加每个Reduce去Map中拿数据的并行数;
(5)集群性能可以的前提下,增大Reduce端存储数据内存的大小。
3)IO传输:
采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
压缩:
(1)map输入端主要考虑数据量大小和切片,支持切片的有Bzip2、LZO。注意:LZO要想支持切片必须创建索引;
(2)map输出端主要考虑速度,速度快的snappy、LZO;
(3)reduce输出端主要看具体需求,例如作为下一个mr输入需要考虑切片,永久保存考虑压缩率比较大的gzip。
4)整体:
(1)NodeManager默认内存8G,需要根据服务器实际配置灵活调整,例如128G内存,配置为100G内存左右,yarn.nodemanager.resource.memory-mb。
(2)单任务默认内存8G,需要根据该任务的数据量灵活调整,例如128m数据,配置1G内存,yarn.scheduler.maximum-allocation-mb。
(3)mapreduce.map.memory.mb:控制分配给MapTask内存上限,如果超过会kill掉进程(报:Container is running beyond physical memory limits. Current usage:565MB of512MB physical memory used;Killing Container)。默认内存大小为1G,如果数据量是128m,正常不需要调整内存;如果数据量大于128m,可以增加MapTask内存,最大可以增加到4-5g。
(4)mapreduce.reduce.memory.mb:控制分配给ReduceTask内存上限。默认内存大小为1G,如果数据量是128m,正常不需要调整内存;如果数据量大于128m,可以增加ReduceTask内存大小为4-5g。
(5)mapreduce.map.java.opts:控制MapTask堆内存大小。(如果内存不够,报:java.lang.OutOfMemoryError)
(6)mapreduce.reduce.java.opts:控制ReduceTask堆内存大小。(如果内存不够,报:java.lang.OutOfMemoryError)
(7)可以增加MapTask的CPU核数,增加ReduceTask的CPU核数
(8)增加每个Container的CPU核数和内存大小
(9)在hdfs-site.xml文件中配置多目录
(10)NameNode有一个工作线程池,用来处理不同DataNode的并发心跳以及客户端并发的元数据操作。dfs.namenode.handler.count=20 * log2(Cluster Size),比如集群规模为10台时,此参数设置为60。
10、请描述mapReduce中combiner的作用是什么,一般使用情景,哪些情况不需要,及和 reduce的区别
(1)Combiner是MR程序中Mapper和Reducer之外的一种组件。
(2)Combiner组件的父类就是Reducer。
(3)Combiner和Reducer的区别在于运行的位置
Combiner是在每一个MapTask所在的节点运行;
Reducer是接收全局所有Mapper的输出结果;
(4)Combiner的意义就是对每一个MapTask的输出进行局部汇总,以减小网络传输量。
(5)Combiner能够应用的前提是不能影响最终的业务逻辑,而且,Combiner的输出kv应该跟Reducer的输入kv类型要对 应起来。
①作用
每一个map可能会产生大量的输出,Combiner的作用就是在map端对输出先做一次合并,减少传输到reducer的数据量。
②使用场景
Combiner最基本是实现本地key的归并,Combiner具有类似本地的reduce功能。
如果不用Combiner,那么,所有的结果都是reduce完成,效率会相对低下。
使用Combiner,先完成的map会在本地聚合,提升速度。
注意:Combiner的输出是Reducer的输入,如果Combiner是可插拔的,添加Combiner绝不能改变最终的计算结果。所以Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。
③区别
combiner是在每一个maptask所在的节点运行
reduce是接收全局的mapper的输出结果
对于Combiner有几点需要说明的是:
有很多人认为这个combiner和map输出的数据合并是一个过程,其实不然,map输出的数据合并只会产生在有数据spill出的时候,即进行merge操作。
与mapper与reducer不同的是,combiner没有默认的实现,需要显式的设置在conf中才有作用。
并不是所有的job都适用combiner,只有操作满足结合律的才可设置combiner。combine操作类似于:opt(opt(1, 2, 3), opt(4, 5, 6))。如果opt为求和、求最大值的话,可以使用,但是如果是求中值的话,不适用。
一般来说,combiner和reducer它们俩进行同样的操作。
但是:特别值得注意的一点,一个combiner只是处理一个结点中的的输出,而不能享受像reduce一样的输入(经过了shuffle阶段的数据)
11、MapReduce的工作原理,请举例子说明mapreduce是怎么运行的?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gy8nTPW0-1623747121417)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606162114173.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OPOJPyL8-1623747121418)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210606162129859.png)]
上面的流程是整个 MapReduce 最全工作流程,但是 Shuffle 过程只是从第 7 步开始到第
16 步结束,具体 Shuffle 过程详解,如下:
(1)MapTask 收集我们的 map()方法输出的 kv 对,放到内存缓冲区中
(2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
(3)多个溢出文件会被合并成大的溢出文件
(4)在溢出过程及合并的过程中,都要调用 Partitioner 进行分区和针对 key 进行排序
(5)ReduceTask 根据自己的分区号,去各个 MapTask 机器上取相应的结果分区数据
(6)ReduceTask 会抓取到同一个分区的来自不同 MapTask 的结果文件,ReduceTask 会将这些文件再进行合并(归并排 序)
(7)合并成大文件后,Shuffle 的过程也就结束了,后面进入 ReduceTask 的逻辑运算过程(从文件中取出一个一个的键 值对 Group,调用用户自定义的 reduce()方法)
注意:
(1)Shuffle 中的缓冲区大小会影响到 MapReduce 程序的执行效率,原则上说,缓冲区越大,磁盘 io 的次数越少,执行 速度就越快。
(2)缓冲区的大小可以通过参数调整,参数:mapreduce.task.io.sort.mb 默认 100M。
12、如果没有定义partitioner,那数据在被送达reduce前是如何呗分区的?
如果没有自定义partitioner,则默认的partition算法,即根据每一条数据key的hashcode值魔运算(%)reduce的数量,得到的数字就是”分区号“
13、MapReduce怎么实现TonN?
可以自定义groupingcomparator,或者在map端对数据进行排序,然后在reduce输出时,控制只输出前n个数,就可以达到topn输出的目的
14、有可能使Hadoop任务输出到多个目录/mysql/等等中吗?可以的话 怎么做?
可以 ,采用自定义outputformat
实现步骤:
1自定义outputformat
2改写recordwriter,具体改写输出数据的方法write()
15、简述Hadoop实现join的几种方法以及每种方法的实现
Map 端的主要工作:为来自不同表或文件的 key/value 对,打标签以区别不同来源的记
录。然后用连接字段作为 key,其余部分和新加的标志作为 value,最后进行输出。
Reduce 端的主要工作:在 Reduce 端以连接字段作为 key 的分组已经完成,我们只需要
在每一个分组当中将那些来源于不同文件的记录(在 Map 阶段已经打标志)分开,最后进
行合并就 ok 了。
2)map join
在map端缓存多张表,提前处理业务逻辑,这样增加map端业务,减少reduce端数据的压力,尽可能的减少数据倾斜。
具体办法:采用distributedcache
(1)在mapper的setup阶段,将文件读取到缓存集合中。
(2)在驱动函数中加载缓存。
job.addCacheFile(new URI(“file:/e:/mapjoincache/pd.txt”));// 缓存普通文件到task运行节点
16、请简述Hadoop怎样实现二级排序
对map端输出的key进行排序,实现compareTo方法。在compareTo方法中排序的条件有两个
17、参考下面的MR系统的场景
–hdfs块的大小为64M
–输入类型为FileInputFormat
–有三个文件的大小分别是:64kb 65Mb 127MB
Hadoop框架会把这些文件拆分为多少块?
5块:64kb 64M 1M 64M 63m
18、Hadoop中RecordReader的作用是什么?
自定义RecordRedder可以读取不同类型文件
( 1 )以怎样的方式从分片中读取一条记录,每读取一条记录都会调用 RecordReader 类;
( 2 )系统默认的 RecordReader 是 LineRecordReader
( 3 ) LineRecordReader 是用每行的偏移量作为 map 的 key ,每行的内容作为 map 的 value ;
( 4 )应用场景:自定义读取每一条记录的方式;自定义读入 key 的类型,如希望读取的 key 是
文件的路径或名字而不是该行在文件中的偏移量。
19、给你一个g的数据文件。分别有id,name,mark,source 四个字段,按照mark分组,id排序,手写一个mapreduce?其中有几个mapper
方案一:在map端对mark和id进行排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QOWXQQEC-1623747121420)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607151922679.png)]
方案二:在map端对mark进行排序,在reduce端对id进行分组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3fFmYttr-1623747121422)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607153205823.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-najgy9nE-1623747121424)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607153247806.png)]
2)几个mapper
1204m/128=8块
4、Yarn
1、简述Hadoop1与Hadoop2的架构异同
加入了yarn解决了资源调度问题
加入了对zookeeper的支持实现比较可靠的高可用
2、为什么会产生yarn,他解决了什么问题,有什么优势
Yarn最主要的功能就是解决运行的用户程序与yarn框架完全解耦
yarn上可以运行各种类型的分布式运算程序(mapreduce只是其中一种)比如mapreduce、storm程序、spark程序…
3、MR作用提交全过程
1)作业提交过程之yarn
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPwEtImB-1623747121426)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607154248662.png)]
2)作业提交过程之mapreduce/hdfs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7DwjSp06-1623747121427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607154302533.png)]
作业提交全过程详解
(1)作业提交
第 1 步:Client 调用 job.waitForCompletion 方法,向整个集群提交 MapReduce 作业。
第 2 步:Client 向 RM 申请一个作业 id。
第 3 步:RM 给 Client 返回该 job 资源的提交路径和作业 id。
第 4 步:Client 提交 jar 包、切片信息和配置文件到指定的资源提交路径。
第 5 步:Client 提交完资源后,向 RM 申请运行 MrAppMaster。
(2)作业初始化
第 6 步:当 RM 收到 Client 的请求后,将该 job 添加到容量调度器中。
第 7 步:某一个空闲的 NM 领取到该 Job。
第 8 步:该 NM 创建 Container,并产生 MRAppmaster。
第 9 步:下载 Client 提交的资源到本地。
(3)任务分配
第 10 步:MrAppMaster 向 RM 申请运行多个 MapTask 任务资源。
第 11 步:RM 将运行 MapTask 任务分配给另外两个 NodeManager,另两个 NodeManager分别领取任务并创建容器。
(4)任务运行
第 12 步:MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个NodeManager 分别启动 MapTask, MapTask 对数据分区排序。
第13步:MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。
第 14 步:ReduceTask 向 MapTask 获取相应分区的数据。
第 15 步:程序运行完毕后,MR 会向 RM 申请注销自己。
(5)进度和状态更新
YARN 中的任务将其进度和状态(包括 counter)返回给应用管理器, 客户端每秒(通过
mapreduce.client.progressmonitor.pollinterval 设置)向应用管理器请求进度更新, 展示给用户。
(6)作业完成
除了向应用管理器请求作业进度外, 客户端每 5 秒都会通过调用 waitForCompletion()来检查作业是否完成。时间间隔可以通过 mapreduce.client.completion.pollinterval 来设置。作业完成之后, 应用管理器和 Container 会清理工作状态。作业的信息会被作业历史服务器存储以备之后用户核查。
4、HDFS的数据压缩算法?以及每种算法的应用场景
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作业的输入
5、Hadoop的调度器总结
目前,Hadoop 作业调度器主要有三种:FIFO、容量(Capacity Scheduler)和公平(Fair Scheduler)。Apache Hadoop3.1.3 /2.x 默认的资源调度器是 Capacity Scheduler。
CDH 框架默认调度器是 Fair Scheduler。
FIFO 调度器(First In First Out):单队列,根据提交作业的先后顺序,先来先服务。
优点:简单易懂;
缺点:不支持多队列,生产环境很少使用;
Capacity Scheduler 是 Yahoo 开发的多用户调度器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vExRl1ob-1623747121429)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607155246338.png)]
Fair Schedulere 是 Facebook 开发的多用户调度器。
并发度特别高,对集群要求很高
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tzawNkeg-1623747121431)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210607155321235.png)]
6、mapreduce推测执行算法以及原理
1)作业完成时间取决于最慢的任务完成时间一个作业由若干个Map任务和Reduce任务构成。因硬件老化、软件Bug等,某些任务可能运行 非常慢。
典型案例:系统中有99%的Map任务都完成了,只有少数几个Map老是进度很慢,完不成,怎么办?
2)推测执行机制:
发现拖后腿的任务,比如某个任务运行速度远慢于任务平均速度。为拖后腿任务启动一个备份任务,同时运行。谁先运行完,则采用谁的结果。
3)执行推测任务的前提条件
(1)每个task只能有一个备份任务;
(2)当前job已完成的task必须不小于0.05(5%)
(3)开启推测执行参数设置。Hadoop2.7.2 mapred-site.xml文件中默认是打开的
<property>
<name>mapreduce.map.speculative</name>
<value>true</value>
<description>If true, then multiple instances of some map tasks
may be executed in parallel.</description>
</property>
<property>
<name>mapreduce.reduce.speculative</name>
<value>true</value>
<description>If true, then multiple instances of some reduce tasks may be executed in
parallel.</description>
</property>
4)不能启用推测执行机制情况
(1)任务间存在严重的负载倾斜;
(2)特殊任务,比如任务向数据库中写数据。
5)算法原理:
假设某一时刻,该任务T的执行任务为progress,则可通过一定的算法推测出该任务的最终完成时时刻estimateEndTime,另一方面,如果此刻为该任务启动一个备份任务,则可推断出它可能的完成时刻estimateEndTime;于是可得以下几个公式:
estimateEndTime = estimateRunTime + taskStartTime
推测执行完时刻(60s) = 推测运行时间(60s) + 任务启动时刻(0)
estimateRunTime = ( currentTimestamp - taskStartTime ) / progress
推测运行时间(60s) = (当前时刻(6) - 任务启动时刻(0) ) /任务运行比例(10%)
estimateEndTime = currentTimestamp + averageRunTime
备份任务推测完成时刻(16s) = 当前时刻(6s) + 运行完成任务的平均时间(10s)
1.MR总是选择(‘estimateEndTime - estimateEndTime ’)差值最大的任务,并为之启动备份任务。
2.为了防止大量任务同时启动备份造成的资源浪费,MR为每个作业设置了同时启动的备份任务数目上限。
3.推测执行机制实际采用了经典的优化算法:以空间换时间,它同时启动多个相同任务处理相同的数据,并让这些任务竞争以缩短数据处理时间,很显然,这种方法需要占用更多的计算资源。在集群资源紧缺的情况下,应合理使用该机制,争取在多用少量资源的情况下,减少作业的计算时间
五、优化
1. MapReduce****跑得慢的原因?(☆)**
Mapreduce 程序效率的瓶颈在于两点:
\1. 计算机性能
CPU、内存、磁盘健康、网络
\2. I/O 操作优化
(1)数据倾斜
(2)map和reduce数设置不合理
(3)reduce等待过久
(4)小文件过多
(5)大量的不可分块的超大文件
(6)spill次数过多
(7)merge次数过多等。
2. MapReduce优化方法 (☆)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vg1Ul1jI-1623747121432)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210610002112834.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDDNLaph-1623747121435)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210610002135587.png)]
\1. 数据输入
(1)合并小文件:在执行mr任务前将小文件进行合并,大量的小文件会产生大量的map任务,增大map任务装载次数,而任务的装载比较耗时,从而导致 mr 运行较慢。
(2)采用ConbinFileInputFormat来作为输入,解决输入端大量小文件场景。
\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.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计算也要内存,所以要根据作业的运行情况进行调整。
\4. IO传输
(1)采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。
(2)使用SequenceFile二进制文件
\5. 数据倾斜问题
(1)数据倾斜现象
数据频率倾斜——某一个区域的数据量要远远大于其他区域。
数据大小倾斜——部分记录的大小远远大于平均值。
(2)减少数据倾斜的方法
方法1:抽样和范围分区
可以通过对原始数据进行抽样得到的结果集来预设分区边界值。
方法2:自定义分区
另一个抽样和范围分区的替代方案是基于输出键的背景知识进行自定义分区。例如,如果map输出键的单词来源于一本书。其中大部分必然是省略词(stopword)。那么就可以将自定义分区将这部分省略词发送给固定的一部分reduce实例。而将其他的都发送给剩余的reduce实例。
方法3:Combine
使用Combine可以大量地减小数据频率倾斜和数据大小倾斜。在可能的情况下,combine的目的就是聚合并精简数据。
方法4:采用Map Join,尽量避免Reduce Join
\6. 常用的调优参数
3. HDFS小文件优****化方法 (☆)
\1. HDFS小文件弊端:
HDFS上每个文件都要在namenode上建立一个索引,这个索引的大小约为150byte,这样当小文件比较多的时候,就会产生很多的索引文件,一方面会大量占用namenode的内存空间,另一方面就是索引文件过大是的索引速度变慢。
\2. 解决的方式:
(1)在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS。
(2)在业务处理之前,在HDFS上使用MapReduce程序对小文件进行合并。
(3)在MapReduce处理时,可采用CombineTextInputFormat提高效率。
4. Hadoop自带小文件解决方案
1**)在数据采集的时候,就将小文件或小批数据合成大文件再上传** HDFS**(数据源头)**
2**)Hadoop Archive(存储方向)**
是一个高效的将小文件放入 HDFS 块中的文件存档工具,能够将多个小文件打包成一
个 HAR 文件,从而达到减少 NameNode 的内存使用
3**)CombineTextInputFormat(计算方向)**
CombineTextInputFormat 用于将多个小文件在切片过程中生成一个单独的切片或者少
量的切片。
4**)开启** uber 模式,实现 JVM 重用(计算方向)
默认情况下,每个 Task 任务都需要启动一个 JVM 来运行,如果 Task 任务计算的数据
量很小,我们可以让同一个 Job 的多个 Task 运行在一个 JVM 中,不必为每个 Task 都开启
一个 JVM。
5、mapreduce怎么解决数据均衡问题,如何确定分区号?
数据均衡问题指的就是某个节点或者某几个节点的任务运行的比较慢,拖慢了整个Job的进度。
实际上数据均衡问题就是数据倾斜问题,解决方案同解决数据倾斜的方案。
MapReduce中分区默认是按hashcode来分的,用户可以自定义分区类,需要继承系统的Partitioner 类,重写getPartition()方法即可
6、Hadoop中job和tasks之间的区别是什么?
Job是我们对一个完整的mapreduce程序的抽象封装,一个job中可以有多个tasks
Task是job运行时,每一个处理阶段的具体实例,如map task,reduce task,maptask和reduce task都会有多个并发运行的实例
7、减少数据倾斜的方法
(1)首先检查是否空值过多造成的数据倾斜
生产环境,可以直接过滤掉空值;如果想保留空值,就自定义分区,将空值加随机数打
散。最后再二次聚合。
(2)能在 map 阶段提前处理,最好先在 Map **阶段处理。如:Combiner、**MapJoin
(3)设置多个 reduce 个数