Q1、 mapreduce流程?
Map阶段:
1:读取输入文件的内容,并解析成键值对(<key, value>)的形式,输入文件中的每一行被解析成一个<key, value>对,每个<key, value>对调用一次map()函数。
2:用户写map()函数,对输入的<key,value>对进行处理,并输出新的<key,value>对。
3:对Step 2中得到的<key,value>进行分区操作。
4:不同分区的数据,按照key值进行排序和分组,具有相同key值的value则放到同一个集合中。
5(可选):分组后的数据进行规约。
Reduce阶段:
1:对于多个map任务的输出,按照不同的分区,通过网络传输到不同的Reduce节点。
2:对多个map任务的输出结果进行合并、排序,用户书写reduce函数,对输入的key、value进行处理,得到新的key、value输出结果。
3:将reduce的输出结果保存在文件中。
Q2、 如何决定一个job中需要多少个maptask和reducetask?
一、影响map个数,即split个数的因素主要有:
1)HDFS块的大小,即HDFS中dfs.block.size的值。如果有一个输入文件为1024m,当块为
256m时,会被划分为4个split;当块为128m时,会被划分为8个split。
2)文件的大小。当块为128m时,如果输入文件为128m,会被划分为1个split;当块为256m,会被划分为2个split。
3)文件的个数。FileInputFormat按照文件分割split,并且只会分割大文件,即那些大小超过HDFS块的大小的文件。如果HDFS中dfs.block.size设置为64m,而输入的目录中文件有100个,则划分后的split个数至少为100个。
4)splitsize的大小。分片是按照splitszie的大小进行分割的,一个split的大小在没有设置的情况下,默认等于hdfs block的大小。但应用程序可以通过两个参数来对splitsize进行调节。
map个数的计算公式如下:
splitsize=max(minimumsize,min(maximumsize,blocksize))。
如果没有设置minimumsize和maximumsize,splitsize的大小默认等于blocksize
二、reduce端的个数取决于用户的需求,默认是有一个reduce,可以在代码中声明
reduce的输出个数
Q3、 mapreduce如何实现数据的去重?
在map阶段,map方法的输出key也应该是数据,value 任意值都可以。而map的输入key和value 是已知的,key为每行文本首地址相对于整个文本首地址的偏移量,value 是每行文本,因此在map方法从输入到输出的过程中,只需要将输入的value 赋给输出的key即可。 在mapreduce整个框架下,在map输出和reduce输入之间还有一个shuffule过程,这个是系统自动完成的。
Q4、 我们在开发分布式计算 job 时,是否可以去掉 reduce()阶段?为什么?
可以,例如我们的集群就是为了存储文件而设计的,不涉及到数据的计算,就可以将mapReduce都省掉。去掉之后就不排序了,不进行shuffle操作了。
比如,流量运营项目中的行为轨迹增强功能部分。
Q5、 MapReduce中排序发生在哪几个阶段?这些排序是否可以避免?为什么?
1、 map最后阶段进行partition分区,一般使用job.setPartitionerClass设置的类,如果没有自定义Key的hashCode()方法进行分区。在map阶段写出到环形缓冲区,在环形缓冲区溢写时会进行一次排序,每个分区内部调用job.setSortComparatorClass设置的key的比较函数类进行排序,如果没有则使用Key的实现的compareTo方法。
2、 在归并每一个maptask的环形缓冲区的所有溢写文件的时候也会再次进行排序
3、 当reduce接收到所有map传输过来的数据之后,对每一个分区的数据进行merge并排序,调用job.setSortComparatorClass设置的key比较函数类对所有数据对排序,如果没有则使用Key的实现的compareTo方法。
4、紧接着使用job.setGroupingComparatorClass设置的分组函数类,进行分组,同一个Key的value放在一个迭代器里面。如果未指定GroupingComparatorClass则则使用Key的实现的compareTo方法来对其分组。
Hadoop1.0中不可避免 hadoop2.0中可以关闭,将reducetask设置为0
Q6、 MapReduce join
1.map join 缺点:只适合大小表join 优点:不会出现数据倾斜
实现:将小表数据加入缓存分发到各个计算节点,按连接关键字建立索引
job.addCacheFile(new URI(“xxxxxxx”));
job.setNumReduceTasks(0);
2.reduce join 缺点:会出现数据倾斜
Q7、 MapReduce数据倾斜
- 利用combiner提前进行reduce,把一个mapper中的相同key进行了聚合,减少shuffle过程中数据量,以及reduce端的计算量。这种方法可以有效的缓解数据倾斜问题,但是如果导致数据倾斜的key大量分布在不同的mapper的时候,这种方法就不是很有效了。
- 局部聚合加全局聚合。即进行两次mapreduce,第一次在map阶段对那些导致了数据倾斜的key 加上1-n的随机前缀,这样之前相同的key 也会被分到不同的reduce中,进行聚合,这样的话就有那些倾斜的key进行局部聚合,数量就会大大降低。然后再进行第二次mapreduce这样的话就去掉随机前缀,进行全局聚合。不过进行两次mapreduce,性能稍微比一次的差些。
Q8、 Yarn支持的调度器和硬件资源种类?
YARN自带了三种常用的调度器,分别是FIFO,Capacity Scheduler和Fair Scheduler,其中,第一个是默认的调度器,它属于批处理调度器,而后两个属于多租户调度器,它采用树形多队列的形式组织资源,更适合公司应用场景
YARN支持内存和CPU两种资源类型的管理和分配:YARN对内存资源和CPU资源采用了不同的资源隔离方案。对于内存资源,为了能够更灵活的控制内存使用量,YARN采用了进程监控的方案控制内存使用,即每个NodeManager会启动一个额外监控线程监控每个container内存资源使用量,一旦发现它超过约定的资源量,则会将其杀死;对于CPU资源,则采用了Cgroups进行资源隔离
Q9、 Yarn作业执行流程
1、用户向 YARN 中提交应用程序,其中包括 MRAppMaster 程序,启动 MRAppMaster 的命令,用户程序等。
2、ResourceManager 为该程序分配第一个 Container,并与对应的 NodeManager 通讯,要求它在这个 Container 中启动应用程序 MRAppMaster。
3、MRAppMaster 首先向 ResourceManager 注册,这样用户可以直接通过 ResourceManager 查看应用程序的运行状态,然后将为各个任务申请资源,并监控它的运行状态,直到运行结束,重复 4 到 7 的步骤。
4、MRAppMaster 采用轮询的方式通过 RPC 协议向 ResourceManager 申请和领取资源。
5、一旦 MRAppMaster 申请到资源后,便与对应的 NodeManager 通讯,要求它启动任务。
6、NodeManager 为任务设置好运行环境(包括环境变量、JAR 包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
7、各个任务通过某个 RPC 协议向 MRAppMaster 汇报自己的状态和进度,以让 MRAppMaster 随时掌握各个任务的运行状态,从而可以在任务败的时候重新启动任务。
Q10、 编写MapReduce作业时,如何做到在Reduce阶段,先对key排序,再对value排序?
答:该问题通常称为“二次排序”,最常用的方法是将value放到key中,实现一个组合Key,然后自定义key排序规则(为key实现一个WritableComparable)。