字节跳动大数据开发面经答案汇总之Hadoop篇
所有题目链接:史上最全的大数据开发面经及答案汇总【字节跳动】
1.介绍一下Hadoop hadoop是什么
Hadoop是一个由Apache基金会所开发的分布式系统基础架构,主要解决海量数据存储与计算的问题,主要包括HDFS、MapReduce和Yarn框架。
2.谷歌的三篇论文是否了解,三驾马车GFS,BigTable,MapReduce
了解(建议浅看一下)
3.hdfs源码你知道的话,讲讲元数据怎么管理的?
Namenode对元数据的管理采用了三种形式:
- 内存元数据:基于内存存储元数据,元数据比较完整
- fsimage文件:磁盘元数据镜像文件,在NameNode工作目录中,它不包含block所在的Datanode 信息
- edits文件:数据操作日志文件,用于衔接内存元数据和fsimage之间的操作日志,可通过日志运算出元数据
4.hdfs 你知道namenode的问题吗?怎么解决?应该就是联邦机制
为了能够水平扩展Namenode,HDFS2.X提供了Federation架构。Federation架构的HDFS集群可以定义多个Namenode/Namespace,这些Namenode之间相互独立,各自分工管理自己的命名空间。HDFS集群中的Datanode提供数据块的共享存储功能,每个Datanode都会向集群中所有的Namenode注册,且周期性地向所有的Namenode发送心跳和块汇报,然后执行Namenode通过响应发回的Namenode指令。
5.hdfs写数据流程
- 首先客户端会向namenode进行请求,然后namenode会检查该文件是否已经存在,如果不存在,就会允许客户端上传文件;
- 客户端再次向namenode请求第一个block上传到哪几个datanode节点上,假设namenode返回了三个datanode节点;
- 那么客户端就会向datanode1请求上传数据,然后datanode1会继续调用datanode2,datanode2会继续调用datanode3,那么这个通信管道就建立起来了,紧接着dn3,dn2,dn1逐级应答客户端;
- 然后客户端就会向datanode1上传第一个block,以packet为单位(默认64k),datanode1收到后就会传给datanode2,dn2传给dn3
- 当第一个block传输完成之后,客户端再次请求namenode上传第二个block。【写的时候,是串行的写入 数据块】
6.namenode如果挂掉了怎么办 【HA配置】
- 当namenode发生故障宕机时,secondary namenode会保存所有的元数据信息,在namenode重启的时候,secondary namenode会将元数据信息发送给namenode。
7.说一下mapredeuce
- map阶段:首先通过把输入目录下的文件进行逻辑切片,默认大小等于block大小,并且每一个切片由一个maptask来处理,同时将切片中的数据解析成<key,value>的键值对,k表示偏移量,v表示一行内容;紧接着调用Mapper类中的map方法。将每一行内容进行处理,解析为<k,v>的键值对,在wordCount案例中,k表示单词,v表示数字1 ;
- shuffle阶段:map端shuffle:将map后的<k,v>写入环形缓冲区【默认100m】,一半写元数据信息(key的起始位置,value的起始位置,value的长度,partition号),一半写<k,v>数据,等到达80%的时候,就要进行spill溢写操作,溢写之前需要对key按照【分区算法默认是,分区号是根据key的hashcode对reduce task个数取模得到的。这时候有一个优化方法可选,combiner合并,就是预聚合的操作,将有相同Key 的Value 合并起来, 减少溢写到磁盘的数据量,只能用来累加、最大值使用,不能在求平均值的时候使用】;然后到文件中,并且进行(多个溢写文件);reduce端shuffle:reduce会同一分区的各个maptask的结果到内存中,如果放不下,就会溢写到磁盘上;然后对内存和磁盘上的数据进行(这样就可以满足将key相同的数据聚在一起); 【Merge有3种形式,分别是内存到内存,内存到磁盘,磁盘到磁盘。默认情况下第一种形式不启用,第二种Merge方式一直在运行(spill阶段)直到结束,然后启用第三种磁盘到磁盘的Merge方式生成最终的文件。】
- reduce阶段:key相同的数据会调用一次reduce方法,每次调用产生一个键值对,最后将这些键值对写入到HDFS文件中。
8.哪个阶段最费时间,环形缓冲区的调优以及什么时候需要调
shuffle:排序和溢写磁盘 原则上说,缓冲区越大,磁盘 io 的次数越少,执行速度就越快
9.环形缓冲区了不了解?说一下他的那个阈值高低的影响
- 环形缓冲区底层就是一个数组,默认大小是100M
- 数组中存放着key和value的数据,以及关于key和value的元数据信息。每个key, value对应一个元数据,元数据由4个int组成,第一个int存放value的起始位置,第二个int存放key的起始位置,第三个int存放partition,第四个int存放value的长度。
- key/value数据和元数据在环形缓冲区中的存储是由equator(赤道)分隔的,key/value按照索引递增的方向存储,元数据则按照索引递减的方向存储。将数组抽象为一个环形结构之后,以equator为界,key/value顺时针存储,元数据逆时针存储。
10.写一个wordcount
public class WordcountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{ Text k = new Text(); IntWritable v = new IntWritable(1); @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 1 获取一行 String line = value.toString(); // 2 切割 String[] words = line.split(" "); // 3 输出 for (String word : words) { k.set(word); context.write(k, v); } } } public class WordcountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{ int sum; IntWritable v = new IntWritable(); @Override protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException { // 1 累加求和 sum = 0; for (IntWritable count : values) { sum += count.get(); } // 2 输出 v.set(sum); context.write(key,v); } }
11.WordCount在MapReduce中键值对变化
<偏移量, 一行数据> -> <单词1, 1> <单词2, 1> .... -> <单词1,10> <单词2,15>
12.map端为什么要排序?
是为了通过外排(外部排序)降低内存的使用量:因为reduce阶段需要分组,将key相同的放在一起进行规约,使用了两种算法:hashmap和sort,如果在reduce阶段sort排序(内部排序),太消耗内存,而map阶段的输出是要溢写到磁盘的,在磁盘中外排可以对任意数据量分组(只要磁盘够大),所以,map端排序(shuffle阶段),是为了减轻reduce端排序的压力。
13.map端输出的文件组织形式是什么样的?
多个溢写文件合并后的大文件
14.reduce怎么知道从哪里下载map输出的文件
通过MRAPPMaster获取哪些节点有map输出,当map执行结束后,会汇报给MRAPPMaster。reduce中的一个线程会定期询问MRAPPMaster以便获取map输出的位置
15.如果map输出太多小文件怎么办
开启combiner合并,但是在求平均值的时候是不能使用的
16.MapReduce优化的case
- 输入端:合并小文件 combineinputformat
- map端:提高环形缓冲区的大小,减少IO次数 开启combiner