大数据面试题锦囊【更新中...】

目录

Hadoop面试题

1:MapReduce原理及执行步骤

MapReduce是一种分布式计算模型,由Google提出,主要用于搜索领域,解决海量数据的计算问题

MapReduce由两个阶段组成:Map和Reduce

Map阶段:

1:框架会把输入文件(夹)划分为很多InputSplit,默认,每个HDFS的Block对应一个InputSplit。通过RecordReader类,把每个InputSplit解析成一个个。默认,每一行数据,会被解析成一个

2:框架调用Mapper类中的map(...)函数,map函数的输入是,输出是。一个InputSplit对应一个Map Task

3:框架对map函数输出的进行分区。不同分区中的由不同的Reduce Task处理,默认只有1个分区

4:框架对每个分区中的数据,按照k2进行排序、分组。分组,指的是相同k2的v2分成一个组

5:在Map阶段,框架可以执行Combiner操作,【可选】

6:框架会把Map Task输出的写入Linux的磁盘文件

至此,整个Map阶段执行结束

Reduce阶段:

1:框架对多个Map Task的输出,按照不同的分区,通过网络Copy到不同的Reduce节点,这个过程称作Shuffle

2:框架对Reduce节点接收到的相同分区的数据进行合并、排序、分组

3:框架调用Reducer类中的reduce方法,输入,输出。一个调用一次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把存储该数据的文件删除。

results matching ""

    No results matching ""