大数据面试题锦囊【更新中...】
目录
Hadoop面试题
1:MapReduce原理及执行步骤
MapReduce是一种分布式计算模型,由Google提出,主要用于搜索领域,解决海量数据的计算问题
MapReduce由两个阶段组成:Map和Reduce
Map阶段:
1:框架会把输入文件(夹)划分为很多InputSplit,默认,每个HDFS的Block对应一个InputSplit。通过RecordReader类,把每个InputSplit解析成一个个
2:框架调用Mapper类中的map(...)函数,map函数的输入是
3:框架对map函数输出的
4:框架对每个分区中的数据,按照k2进行排序、分组。分组,指的是相同k2的v2分成一个组
5:在Map阶段,框架可以执行Combiner操作,【可选】
6:框架会把Map Task输出的
至此,整个Map阶段执行结束
Reduce阶段:
1:框架对多个Map Task的输出,按照不同的分区,通过网络Copy到不同的Reduce节点,这个过程称作Shuffle
2:框架对Reduce节点接收到的相同分区的
3:框架调用Reducer类中的reduce方法,输入
4:框架把Reduce的输出结果保存到HDFS中
至此,整个Reduce阶段执行结束
2:NameNode中主要保存了什么数据?
NameNode是整个文件系统的管理节点,它主要维护着整个文件系统的文件目录树,文件/目录的信息和 每个文件对应的数据块列表,并且还负责接收用户的操作请求
- 目录树:表示目录之间的层级关系,就是我们在hdfs上执行ls命令可以看到的那个目录结构信息。
- 文件/目录的信息:表示文件/目录的的一些基本信息,所有者、属组、修改时间、文件大小等信息。
- 每个文件对应的数据块列表:如果一个文件太大,那么在集群中存储的时候会对文件进行切割,这个时候就类似于会给文件分成一块一块的,存储到不同机器上面。所以HDFS还要记录一下一个文件到底被分了多少块,每一块都在什么地方存储着。
3:getSplit是怎么分片的,分片的大小是多少?
split是逻辑分片,在mapTask任务开始前,将文件按照指定的大小进行逻辑切分。每一个部分称之为一个split。
默认情况下,split的大小与block的大小相等,均为128M。
根据FileInputForamt类的getSplits()源码可知
1.先获取三个参数的值,minSize,maxSize,blockSize。
2.然后创建一个分片集合用于存储分片数据。
3.获取文件的所有块信息,进行遍历。
4.得到一个块的状态信息,然后判断是否可以切分。
5.然后根据三个参数获取分片大小。
6.循环判断文件剩余部分是否大于切片大小的1.1倍。
1.大于的话就调用makeSplit方法创建当前块的逻辑分片。
2.不大于的话,就将文件剩余的部分创建一个唯一的最后一个分片。
7.将每一个逻辑分片添加到分片集合中,等待被使用。
分片的大小由minSize,maxSize,blockSize三个参数决定
算法如下:
Math.max(minSize,Math.min(maxSize, blockSize)),其中maxSize是取得longValueMax的值
1.如果blockSize小于maxSize && blockSize 大于 minSize之间,那么split就是blockSize;
2.如果blockSize小于maxSize && blockSize 小于 minSize之间,那么split就是minSize;
3.如果blockSize大于maxSize && maxSize 大于 minSize之间,那么split就是maxSize;
4.如果blockSize大于maxSize && maxSize 小于 minSize之间,那么split就是maxSize(不存在这种关系)。
4:YARN中的任务运行时报错,在Linux命令行下如何查看错误日志信息?
YARN中任务的日志可以通过界面查看,或者使用命令查看
在Linux命令行下查看某一个Job的日志可以使用如下命令:
yarn logs -applicationId application_1527538889175_0001
注意:application_1527538889175_0001是任务的id
5:一个1G的文件,会产生多少个map任务?
Block块默认是128M,所以1G的文件会产生8个Block块
默认情况下InputSplit的大小和Block块的大小一致,每一个InputSplit会产生一个map任务
所以:1024/128=8个map任务
6:1000个文件,每个文件100KB,会产生多少个map任务?
一个文件,不管再小,都会产生一个Block,所以这1000个小文件会产生1000个Block
那最终会产生1000个InputSplit,也就对应着会产生1000个map任务
7:一个140M的文件,会产生多少个map任务?
140M的文件会产生2个Block,那对应的就会产生2个InputSplit了?
注意:这个有点特殊,140M/128M=1.09375<1.1
所以,这个文件只会产生一个InputSplit,也最终也就只会产生1个map 任务。
这个文件其实再稍微大1M就可以产生2个map任务了。
8:如果一行数据被拆分到了两个InputSplit中,会不会有问题?
不会有问题!
通过LineRecordReader这个类的源码可知
如果我们读取到的这个InputSplit不是第一个InputSplit,我们将会丢掉读取出来的第一行数据
因为我们总是通过next()方法多读取一行(会多读取下一个InputSplit的第一行),这样就可以避免读取断行的问题。
9:如何解决Hadoop中小文件的问题?
Hadoop的HDFS和MapReduce都是针对大数据文件来设计的,在小文件的处理上不但效率低下,而且十分消耗内存资源
针对HDFS而言,每一个小文件在namenode中都会占用150字节的内存空间,最终会导致集群中虽然存储了很多个文件,但是文件的体积并不大,这样就没有意义了。
针对MapReduce而言,每一个小文件都是一个Block,都会产生一个InputSplit,最终每一个小文件都会产生一个map任务,这样会导致同时启动太多的Map任务,Map任务的启动是非常消耗性能的,但是启动了以后执行了很短时间就停止了,因为小文件的数据量太小了,这样就会造成任务执行消耗的时间还没有启动任务消耗的时间多,这样也会影响MapReduce执行的效率。
针对这个问题,解决办法通常是选择一个容器,将这些小文件组织起来统一存储
HDFS提供了两种类型的容器,分别是SequenceFile 和 MapFile
SequeceFile是Hadoop 提供的一种二进制文件,这种二进制文件直接将
一般对小文件可以使用这种文件合并,即将小文件的文件名作为key,文件内容作为value序列化到大文件中
但是这个文件有一个缺点,就是它需要一个合并文件的过程,最终合并的文件会比较大,并且合并后的文件查看起来不方便,必须通过遍历才能查看里面的每一个小文件
所以这个SequenceFile 其实可以理解为把很多小文件压缩成一个大的压缩包了。
MapFile是排序后的SequenceFile,MapFile由两部分组成,分别是index和data
index作为文件的数据索引,主要记录了每个Record的key值,以及该Record在文件中的偏移位置。在MapFile被访问的时候,索引文件会被加载到内存,通过索引映射关系可迅速定位到指定Record所在文件位置
因此,相对SequenceFile而言,MapFile的检索效率是高效的,缺点是会消耗一部分内存来存储index数据。
10:介绍一下YARN中的三种调度器
YARN中支持三种调度器
1:FIFO Scheduler:先进先出(first in, first out)调度策略
2:Capacity Scheduler:FIFO Scheduler的多队列版本
3:FairScheduler:多队列,多用户共享资源
FIFO Scheduler:是先进先出的,大家都是排队的,如果你的任务申请不到足够的资源,那你就等着,等前面的任务执行结束释放了资源之后你再执行。这种在有些时候是不合理的,因为我们有一些任务的优先级比较高,我们希望任务提交上去立刻就开始执行,这个就实现不了了。
CapacityScheduler:它是FifoScheduler的多队列版本,就是我们先把集群中的整块资源划分成多份,我们可以人为的给这些资源定义使用场景,例如图里面的queue A里面运行普通的任务,queueB中运行优先级比较高的任务。这两个队列的资源是相互对立的,但是注意一点,队列内部还是按照先进先出的规则。
FairScheduler:支持多个队列,每个队列可以配置一定的资源,每个队列中的任务共享其所在队列的所有资源,不需要排队等待资源
在实际工作中我们一般都是使用第二种,CapacityScheduler,从hadoop2开始,CapacityScheduler也是集群中的默认调度器了
Flume面试题
1:Flume中的Channel是什么?
Channel被设计为Event中转临时缓冲区,存储Source收集并且没有被Sink读取的Event,为平衡Source收集和Sink读取的速度,可视为Flume内部的消息队列。
Channel线程安全并且具有事务性,支持Source写失败写,和Sink读失败重复读的操作。
常见的类型包括Memory Channel,File Channel,Kafka Channel等。
2:介绍一下Memory Channel
读写速度快,但是存储数据量小,Flume 进程挂掉、服务器停机或者重启都会导致数据丢失。
资源充足、不关心数据丢失的场景下可以用。
3:介绍一下Flume中的几种Sink
1:HDFS Sink: 将Event写入HDFS文件存储,能够有效长期存储大量数据。
2:Kafka Sink: Flume通过Kafka Sink将Event写入到Kafka中的主题,其他应用通过订阅主题消费数据。
4:介绍一下Flume中的拦截器
Source将Event写入到Channel之前可以使用拦截器对Event进行各种形式的处理,Source和Channel之间可以有多个拦截器,不同拦截器使用不同的规则处理 Event,包括时间、主机、UUID、正则表达式等多种形式的拦截器。
5:介绍一下Flume中的选择器
Channel Selectors类型包括:Replicating Channel Selector 和Multiplexing Channel Selector
其中Replicating Channel Selector是默认的channel 选择器,它会将Source采集过来的Event发往所有Channel
还有一个 channel选择器是Multiplexing Channel Selector,它表示会根据Event中header里面的值将Event发往不同的Channel
6:了解Flume的负载均衡和故障转移吗?
Sink Processors类型包括这三种:Default Sink Processor、Load balancing Sink Processor和Failover Sink Processor
DefaultSink
Processor是默认的,不用配置sinkgroup,就是咱们现在使用的这种最普通的形式,一个channel后面接一个sink的形式
Load balancing Sink
Processor是负载均衡处理器,一个channle后面可以接多个sink,这多个sink属于一个sink group,根据指定的算法进行轮询或者随机发送,减轻单个sink的压力
Failover Sink
Processor是故障转移处理器,一个channle后面可以接多个sink,这多个sink属于一个sink group,按照sink的优先级,默认先让优先级高的sink来处理数据,如果这个sink出现了故障,则用优先级低一点的sink处理数据,可以保证数据不丢失。
7:如何调整Flume进程使用的内存?
需要调整flume-env.sh脚本中的JAVA_OPTS参数,把export JAVA_OPTS参数前面的#号去掉才会生效。
export JAVA_OPTS="-Xms1024m -Xmx1024m -Dcom.sun.management.jmxremote"
建议这里的Xms和Xmx设置为一样大,避免进行内存交换,内存交换也比较消耗性能。
8:介绍一下Flume中都有哪些核心组件?
Flume的三大核心组件:
Source:数据源
Channel:临时存储数据的管道
Sink:目的地
解释:
Source:数据源:通过source组件可以指定让Flume读取哪里的数据,然后将数据传递给后面的channel
Channel:接受Source发出的数据,可以把channel理解为一个临时存储数据的管道
Sink:从Channel中读取数据并存储到指定目的地
9:在使用Exec Source的时候,tail -F和 tail -f有什么区别?
tail -F
等同于--follow=name --retry,根据文件名进行追踪,并保持重试,即该文件被删除或改名后,如果再次创建相同的文件名,会继续追踪
tail -f
等同于--follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止
在实际工作中我们的日志数据一般都会通过log4j记录,log4j产生的日志文件名称是固定的,每天定时给文件重命名
假设默认log4j会向access.log文件中写日志,每当凌晨0点的时候,log4j都会对文件进行重命名,在access后面添加昨天的日期,然后再创建新的access.log记录当天的新增日志数据。
这个时候如果想要一直监控access.log文件中的新增日志数据的话,就需要使用tail -F
10:介绍一下File Channel
将Event写入磁盘文件,与Memory Channel相比存储容量大,无数据丢失风险。
File Channel数据存储路径可以配置多磁盘文件路径,通过磁盘并行写入提高File Channel性能。
Flume将Event顺序写入到File Channel文件的末尾。可以在配置文件中通过设置maxFileSize参数配置数据文件大小,当被写入的文件大小达到上限的时候,Flume会重新创建新的文件存储写入Event。当一个已经关闭的只读数据文件的Event 被读取完成,并且Sink已经提交读取完成的事务,则Flume把存储该数据的文件删除。