1、HDFS的基本架构
- Namenode :是整个hdfs集群的总入口,存储着hdfs集群的文件元数据(即Metadata)如:client上传文件的文件名,副本数等。
- DataNode :是真正用来负责存储数据的节点,一个namenode就是一个真实的物理主机
- Block :数据块,为了通过多个节点保存大数据集,hdfs将大数据集文件切分成了一块一块的数据块,默认大小是128M
2、简述安装hadoop的步骤
- 使用root账户登录
- 查看当前的主机名:hostname 修改主机名称:vim /etc/hostname
- 重启生效reboot
- 添加主机名称与ip的映射 vim /etc/hosts
- 关闭防火墙 :systemctl stop/disable firewalld
- 安装JDK,配置环境变量:vim /etc/profile source /etc/profile
- 安装hadoop并且配置环境变量
- 配置核心文件: hadoop-env.sh,core-site.xml , mapred-site.xml , hdfs-site.xml
- 配置slaves文件
- 配置ssh免密码登录
- 格式化:hadoop namenode -format
- 启动 start-all.sh
3、Namenode的持久化
- namenode第一次启动格式化就是为了创建fsimage和edits
- 启动的时候产生一个新的空的edits,然后加载edits和fsimage到内存中,此时namenode内存中有最新的元数据信息。
- client开始对namenode发送元数据增删改,这些被记录到edits.inprogress中(查询不会更改元数据,不记录)此时namenode挂了,从起后会从edits中读取元数据,在内存中执行增删改。
- 由于edits中记录增多文件会越来越大,namenode在加载的时候会非常慢,所以需要将edits和fsimage进行合并。
- SecondaryNamenode的所用是对namenode进行edits和fsimage进行合并。
- SecondaryNamenode首先询问namenode是否checkpoint(触发的两个条件是 1:定时时间到了。 2:edits满了)
- checkpoint步骤:让edits产生滚动新的edits.progress以后新的操作写入edits.progress。然后将edits和fsimage拷贝到SecondaryNamenode的本地,加载到内存中合并成新的fsimage.checkpoint,将fsimage.checkpoint拷贝到namenode并且命名为fsimage替换原有的fsimage
4、hadoop shell常用命名
常见目录:hdfs dfs -ls /
上传文件:hdfs dfs -put a.txt /
创建文件: hdfs dfs -mkdir -p /a/b/c
查看文件内容:hdfs dfs -cat /a.txt
复制:hdfs dfs -cp /a.txt /root/b.txt
追加内容:hdfs dfs -appendToFile a.txt /b.txt
下载到本地:hdfs dfs -get /a.txt /root/a.txt
移动:hdfs dfs -mv /a.txt /a/b/
5、hadoop的调度器
1、FIFO调度器(先进先出原则)
2、Capacity Sheduler(容量调度器)
- 支持多个队列,每个队列配置一定的资源,都采用FIFO
- 选择占用小优先级高的先执行
3、Fair Scheduler:多个队列、每个队列的资源可以配置同一个队列根据算法公平共享资源。
5、设置多个Reduce是如何让多个Reduce均分map中统计的数据的?
利用了分区(Partitioner)的概念,一个Reduce会形成一个分区。默认使用的是HashPartitioner,会根据map输出的key做hash运算,去决定map中输出的数据交给哪一个reduce处理
6、自定义分区Partitioner
作用:将map阶段产生的所有kv对分配给不同的reduce task处理,可以将reduce阶段的处理负载进行分摊,实现负载均衡。
7、什么是Combiner合并?
又称之为map端的reduce。主要是对map端局部的数据先进行一次reduce,减小map端输出的数据频繁发送给reduce处理时所带来的的网络压力问题。
作用:通过提前对map端做一次局部的reduce,这样既可以减轻网络压力,又能提高效率。
默认是关闭的。
8、说一下MapReduce整体运行原理
#1.计算切片
有几个切片就有几个map task
#2.环形缓存区
经过map函数的逻辑处理后的数据输出之后,会通过OutPutCollector收集器将数据收集到环形缓存区保存。
环形缓存区的大小默认为100M,当保存的数据达到80%时,就将缓存区的数据溢出到磁盘上保存。
#3.溢出
环形缓存区的数据达到其容量的80%时就会溢出到磁盘上进行保存,在此过程中,程序会对数据进行分区(默认HashPartition)和排序(默认根据key进行快排)
缓存区不断溢出的数据形成多个小文件
#4.合并
溢出的多个小文件各个区合并在一起(0区和0区合并成一个0区),形成大文件
通过归并排序保证区内的数据有序
#5.shuffle
从过程2到过程7之间,即map任务和reduce任务之间的数据流称为shuffle(混洗),而过程5最能体现出混洗这一概念。一般情况下,一个reduce任务的输入数据来自与多个map任务,多个reduce任务的情况下就会出现如过程5所示的,
每个reduce任务从map的输出数据中获取属于自己的那个分区的数据。
#6.合并
运行reducetask的节点通过过程5,将来自多个map任务的属于自己的分区数据下载到本地磁盘工作目录。这多个分区文件通过归并排序合并成大文件,并根据key值分好组(key值相同的,value值会以迭代器的形式组在一起)。
#7.reducetask
reducetask从本地工作目录获取已经分好组并且排好序的数据,将数据进行reduce函数中的逻辑处理。
#8.输出
每个reducetask输出一个结果文件。
10、说明下列的作用:ResourceManager,NodeManager,MRAppMaster,YarnChild
ResourceManager:负责任务资源的统一调度,管理NodeManager资源,启动MRAppMaster
NodeManager:用于管理本机上的计算资源,默认会将本机的计算资源拆分为8个等份,每个等份抽象成Container
MRAppMaster:任何一个执行的任务都会有一个MRAppMaster负责YarnChild任务的执行和监测。
YarnChild:是具体执行的MapTask或者是ReduceTask的统称。
任务执行期间系统会启动MRAppmaster和YarnChild负责任务的执行,一旦任务执行结束MRAppMaster和YarnChild会自动退出。
11、job作业提交过程?
1.向ResourceManager请求运行一个mapreduce程序。
2.ResourceManager返回hdfs地址,告诉客户端将作业运行相关的资源文件上传到hdfs。
3.客户端提交mr程序运行所需的文件(包括作业的jar包,作业的配置文件,分片信息等)到hdfs上。
4.作业相关信息提交完成后,客户端用过调用ResourcrManager的submitApplication()方法提交作业。
5.ResourceManager将作业传递给调度器,调度器的默认调度策略是先进先出。
6.调度器寻找一台空闲的节点,并在该节点隔离出一个容器(container),容器中分配了cpu,内存等资源,并启动MRAppmaster进程。
7.MRAppmaster根据需要运行多少个map任务,多少个reduce任务向ResourceManager请求资源。
8.ResourceManager分配相应数量的容器,并告知MRAppmaster容器在哪。
9.MRAppmaster启动maptask。
10.maptask从HDFS获取分片数据执行map逻辑。
11.map逻辑执行结束后,MRAppmaster启动reducetask。
12.reducetask从maptask获取属于自己的分区数据执行reduce逻辑。
13.reduce逻辑结束后将结果数据保存到HDFS上。
14.mapreduce作业结束后,MRAppmaster通知ResourceManager结束自己,让ResourceManager回收所有资源。
12、在HA集群中如果ZK与NameNode(advice)出现网络上延迟这种情况,ZK会自动切换NameNode(standby)为活跃节点,这个时候集群就出现了多个活跃的NameNode(advice)
也就意味着出现了脑裂的问题!怎么解决?
提示:考察的是JournalNode中的两种功能: 1、同步数据 2、隔离机制
答案:JournalNode有以下两种功能:
1、负责NameNode中edits的同步数据。
2、JournalNode的隔离机制,因为它是唯一个连接着两个NameNode的组件,所以他会第一个发现。为了保证这一时刻只有一个NameNode(advice)活跃,他会使用ssh登录到NameNode节点上,使用kill命令杀死NameNode
13、为什么说MapReduce不擅长处理小文件
默认情况下,TextInputFormat对任务的切片机制是规则切片,不管文件多小,都会是一个单独的切片,都会交给MapTask,如果有大量的小文件,就会产生大量的MapTask,导致处理效率极其低下
优化方法 在数据处理之前,先将小文件合并成大文件,再上传到HDFS上做后续分析
14、什么是MapReduce计算中的数据倾斜?
产生原因
在MapReduce做计算的时候,由于不合理的key,导致出现数据分布不均匀的现象,称之为数据倾斜。
解决思路
选择合适的key作为统计依据,使得数据能够在分区中均匀分布,一般要对分析的数据有一定的预判。
- 方案一 设置Map和Reduce的任务的数量
- 方案二 设置任务运行的并行度
- 方案三 增加相应节点虚拟机的内存大小
- 方案四 自定义Partition
- 方案五 开启map端的压缩
可以减少reduce shuffle过程中的网络带宽,不足之处在于计算过程中需要消耗额外的CPU进行数据的压缩和解压缩。
注意: 此方案适合在集群环境下使用,如果是本地测试会报not a gzip file的错误。如果现有100亿条无序的数字需要进行排序,此时在reduce端下载map端的数据就会占用大量的带宽。 - 方案六 自定义Combiner
先对map端的文件排序结果进行合并优化,再执行reduce端的方法进行处理,这样传输的数据量就会有一个质的下降
注意: 自定义Combiner结果类型必须一致;统计过程必须支持局部计算
15、TotalOrderPartitioner 类提供了三个采样器,分别是:
- SplitSampler 分片采样器:从数据分片中采样数据,该采样器不适合已经排好序的数据
- RandomSampler随机采样器:按照设置好的采样率从一个数据集中采样,是一个优秀的通配采样器
- IntervalSampler间隔采样机:以固定的间隔从分片中采样数据,对于已经排好序的数据效果非常好
16、namenode的safemode是怎么回事?如何才能退出safemode?
namenode在刚启动的时候元数据只有文件块信息,没有文件所在datanode的信息,需要datanode自己向namenode汇报。如果namenode发现datanode汇报的文件块信息没有达到namenode内存中所有文件块的总阈值的一个百分比,namenode就会处于safemode。 只有达到这个阈值,namenode才会推出safemode。也可手动强制退出。
17、MapReduce切片计算方案
- SPLIT_SLOP=1.1,即当划分后剩余文件大小除以splitSize大于128的1.1倍时,会继续循环切分,小于1.1倍时退出循环,将剩下的文件大小归到一个切片上去。
while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
splits.add(makeSplit(path, length-bytesRemaining, splitSize,blkLocations[blkIndex].getHosts(),
blkLocations[blkIndex].getCachedHosts()));
bytesRemaining -= splitSize;
}
18、MapReduce能否对key做全局排序?
可以。
-
方案一
MapReduce只能保证一个分区内的数据是key有序的,一个分区对应一个reduce,因此只有一个reduce就保证了数据全局有序缺点: 不能用到集群的优势。
-
方案二
多个reduce情况下,可以按照key进行分区,通过MapReduce的默认分区函数HashPartition将不同范围的key发送到不同的reduce处理。
例如一个文件中有key值从1到10000的数据,我们使用两个分区,将1到5000的key发送到partition1,然后由reduce1处理,5001到10000的key发动到partition2然后由reduce2处理,reduce1中的key是按照1到5000的升序排序,reduce2中的key是按照5001到10000的升序排序,这样就保证了整个MapReduce程序的全局排序。缺点:
1.当数据量大时会出现OOM(内存溢出)
2.会出现数据倾斜 -
方案三 Hadoop提供了TotalOrderPartitionner类用于实现全局排序的功能,并且解决了OOM和数据倾斜的问题。
TotalOrderPartitioner类提供了数据采样器,对key值进行部分采样,然后按照采样结果寻找key值的最佳分割点,将key值均匀的分配到不同的分区中。