这里写自定义目录标题
- MapReduce概述
- MapReduce特点
- MapReduce框架原理
- Shuffle机制
- 其他关键点
MapReduce概述
- MapReduce ,负责hadoop中的应用程序计算
MapReduce特点
- 1.易于编程
通过简单的实现一些接口,就可完成分布式程序 - 2. 良好的扩展性
可通过简单的增加服务器,提高计算能力 - 3. 高容错性
其中一台机器挂了,可将上面的计算任务转移到另一个节点上运行,不至于该任务运行失败
MapReduce框架原理
–MapReduce框架有Map和Reduce两个阶段
- Map阶段:
– 数据输入后由InputFormat将数据切片,yarn根据切片信息开启相应个数的map Task,map Task通过调用InputFormat中的recordreader()方法将切片信息转换成(K,V)键值对,然后针对每个(K,V)键值对调用Mapper中的map()方法进行计算
- –shuffle:
– map方法之后,reduce方法之前这段处理过程叫shuffle
– 将map()方法输出的(K,V)键值对按key值进行分组转换成reduce()的输入,具体原理见后面shuffle机制原理
- Reduce阶段
– Reduce Task中调用Reducer中的reduce()方法,对shuffle处理后的每组数据进行处理,然后调用OutputFormat中的recordwriter()方法进行输出
Shuffle机制
说明
- –map方法之后,reduce方法之前这段处理过程叫shuffle
原理
- – 1. map方法之后,数据首先进入分区方法,把数据标好分区
- – 2. 然后将数据发送到环形缓冲区,缓冲区默认100M,当数据达到**80%**时就会溢写一个文件到磁盘,溢写前会先进行一次快速排序,所以溢写的文件是分区且区内有序的;写入磁盘前可利用combiner进行合并,减轻I/O压力(前提是不影响业务结果)
- – 3. 溢写出大量文件后就需要对溢写文件进行归并排序(默认10个文件归并一次),最终形成一个大的文件存储到磁盘中,等待reduce端处理(归并后写磁盘前也可对数据进行combiner合并,减轻I/O压力,)
- – 4. reduce端每个reduce Task从所有maptask中拷贝对应分区的数据到内存,当内存不够时就会溢出到磁盘中,拉取完所有数据后,会对内存及磁盘中的数据进行归并排序,然后按照相同的key值进行分组,调用reduce方法对每组数据进行处理
其他关键点
- jobt提交过程
Driver中调用waitForCompletion()提交:
boolean b = job.waitForCompletion(true);
waitForCompletion()中submit()方法中实现真正提交:
this.submit();
submit()方法中首先建立连接(有yarn配置就连接的yarn集群,没有就是本地的):
this.connect();
submit()方法中提交job:
submitter.submitJobInternal(Job.this, Job.this.cluster);
提交job方法中,获取job运行的资源提交路径:
//获取stag路径
Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf);
//获取jobid
JobID jobId = this.submitClient.getNewJobID();
//资源提交路径拼接
Path submitJobDir = new Path(jobStagingArea, jobId.toString());
将jar包、切片信息、配置文件上传到集群中
//拷贝jar包到集群
this.copyAndConfigureFiles(job, submitJobDir);
//计算切片信息并上传到集群
int maps = this.writeSplits(job, submitJobDir);
//配置文件上传
this.writeConf(conf, submitJobFile);
//提交job
status = this.submitClient.submitJob(jobId, submitJobDir.toString(), job.getCredentials());
- 切片原理
切片大小默认等于块大小,即128M,如下图,若不等于块大小会产生增加网络传输时间,增加延时,降低效率
注:默认切片是针对文件切分的,而不是针对整个集群,即:每个文件至少有一个切片
- map task
map task的个数由切片数决定,有几个切片就有几个对应的map task - 分区(partition)
public int getPartition(K key, V value, int numReduceTasks) {
return (key.hashCode() & 2147483647) % numReduceTasks;
}
默认通过对key的hash值进行去符号位,然后再与ReduceTask数量取模得到分区号
可根据实际业务进行自定义分区
注:
若ReduceTask数量>分区数,就会生成空文件part-r-000xx
若ReduceTask数量<分区数,就会异常
若ReduceTask数量=1,所有分区结果会汇总到一个文件中
- reduce task
某种意义上可理解为:reduce task的个数由分区数决定,有几个分区就有几个对应的reduce task