Hadoop之MapReduce面试知识复习
目录
- 谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化?
- FileInputFormat切片机制
- 在一个运行的Hadoop 任务中,什么是InputSplit?
- 自定义InputFormat流程
- Maptask的个数由什么决定?
- MapTask工作机制
- ReduceTask工作机制
- 请描述mapReduce有几种排序及排序发生的阶段
- 请描述mapReduce中combiner的作用是什么,一般使用情景,哪些情况不需要,及和reduce的区别?
- Mapreduce的工作原理,请举例子说明mapreduce是怎么运行的?
- 如果没有定义partitioner,那数据在被送达reducer前是如何被分区的?
- MapReduce 怎么实现 TopN?
- 如何使用mapReduce实现两个表的join?
- 有可能使 Hadoop 任务输出到多个目录中么?如果可以,怎么做?
- 什么样的计算不能用mr来提速,举5个例子
1. 谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化?
已详细总结过,请参考:Hadoop之Hadoop序列化
2. FileInputFormat切片机制
已详细总结过,请参考:Hadoop之InputFormat数据输入详解
3. 在一个运行的Hadoop 任务中,什么是InputSplit?
已详细总结过,可以参考:Hadoop之InputFormat数据输入详解
-
找到你数据存储的目录。
-
开始遍历处理(规划切片)目录下的每一个文件
-
遍历第一个文件ss.txt
-
获取文件大小fs.sizeOf(ss.txt)
-
计算切片大小 computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
-
默认情况下,切片大小=blocksize
-
开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)
-
将切片信息写到一个切片规划文件中
-
整个切片的核心过程在getSplit()方法中完成
-
数据切片只是在逻辑上对输入数据进行分片,并不会在磁盘上将其切分成分片进行存储。InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等
-
注意:block是HDFS物理上存储的数据,切片是对数据逻辑上的划分
-
-
提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启maptask个数。
4. 自定义InputFormat流程
- 自定义一个类继承FileInputFormat
- 改写RecordReader,实现一次读取一个完整文件封装为KV
5. Maptask的个数由什么决定?
- 一个job的map阶段MapTask并行度(个数),由客户端提交job时的切片个数决定。
6. MapTask工作机制
已详细总结过,可以参考:Hadoop之MapTask工作机制
7. ReduceTask工作机制
已详细总结过,可以参考:ReduceTask工作机制
8. 请描述mapReduce有几种排序及排序发生的阶段
排序的分类:
-
部分排序:
MapReduce根据输入记录的键对数据集排序。保证输出的每个文件内部排序。 -
全排序:
如何用Hadoop产生一个全局排序的文件?最简单的方法是使用一个分区。但该方法在处理大型文件时效率极低,因为一台机器必须处理所有输出文件,从而完全丧失了MapReduce所提供的并行架构。
替代方案:首先创建一系列排好序的文件;其次,串联这些文件;最后,生成一个全局排序的文件。主要思路是使用一个分区来描述输出的全局排序。例如:可以为待分析文件创建3个分区,在第一分区中,记录的单词首字母a-g,第二分区记录单词首字母h-n, 第三分区记录单词首字母o-z。 -
辅助排序:(GroupingComparator分组)
Mapreduce框架在记录到达reducer之前按键对记录排序,但键所对应的值并没有被排序。甚至在不同的执行轮次中,这些值的排序也不固定,因为它们来自不同的map任务且这些map任务在不同轮次中完成时间各不相同。一般来说,大多数MapReduce程序会避免让reduce函数依赖于值的排序。但是,有时也需要通过特定的方法对键进行排序和分组等以实现对值的排序。 -
二次排序:
在自定义排序过程中,如果compareTo中的判断条件为两个即为二次排序。 -
自定义排序WritableComparable
bean对象实现WritableComparable接口重写compareTo方法,就可以实现排序
@Override
public int compareTo(FlowBean o) {
// 倒序排列,从大到小
return this.sumFlow > o.getSumFlow() ? -1 : 1;
}
排序发生的阶段:
- 一个是在map side发生在spill后partition前。
- 一个是在reduce side发生在copy后 reduce前。
9. 请描述mapReduce中combiner的作用是什么,一般使用情景,哪些情况不需要,及和reduce的区别?
- Combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量。
- Combiner能够应用的前提是不能影响最终的业务逻辑,而且,Combiner的输出kv应该跟reducer的输入kv类型要对应起来。
- Combiner和reducer的区别在于运行的位置。
- Combiner是在每一个maptask所在的节点运行;
- Reducer是接收全局所有Mapper的输出结果。
10. Mapreduce的工作原理,请举例子说明mapreduce是怎么运行的?
已详细总结过,可以参考:Hadoop之MapReduce工作流程
11. 如果没有定义partitioner,那数据在被送达reducer前是如何被分区的?
如果没有自定义的 partitioning,则默认的 partition 算法,即根据每一条数据的 key的 hashcode 值模运算(%)reduce 的数量,得到的数字就是"分区号"。
12. MapReduce 怎么实现 TopN?
可以自定义groupingcomparator,对结果进行最大值排序,然后再reduce输出时,控制只输出前n个数。就达到了topn输出的目的。
13. 如何使用mapReduce实现两个表的join?
- reduce side join : 在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag),比如:tag=0 表示来自文件File1,tag=2 表示来自文件File2。
- map side join : Map side join 是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task 内存中存在一份(比如存放到hash table 中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table 中查找是否有相同的key 的记录,如果有,则连接后输出即可。
14. 有可能使 Hadoop 任务输出到多个目录中么?如果可以,怎么做?
可以通过自定义outputformat来实现。
- 自定义OutputFormat步骤
- 自定义一个类继承FileOutputFormat。
- 改写recordwriter,具体改写输出数据的方法write()。
15. 什么样的计算不能用mr来提速,举5个例子
- 数据量很小。
- 繁杂的小文件。
- 索引是更好的存取机制的时候。
- 事务处理。
- 只有一台机器的时候。