1、MapReduce代码入口

FileInputFormat.setInputPaths(job, new Path(input)); //设置MapReduce输入格式
job.waitForCompletion(true);

2、InputFormat分析

public abstract class InputFormat<K, V> {
//获取输入文件的分片,仅是逻辑分片,并没有物理分片
public abstract List<InputSplit> getSplits(JobContext context); //创建RecordReader,从InputSplit中读取数据
public abstract RecordReader<K,V> createRecordReader(InputSplit split,TaskAttemptContext context) ;
}

不同的InputFormat会各自实现不同的文件读取方式以及分片方式,每个输入分片(InputSplit)会被单独的map task作为数据源

3、InputSplit

Mapper的输入是一个一个的输入分片(InputSplit)

public abstract class InputSplit {
public abstract long getLength();
public abstract String[] getLocations();
} public class FileSplit extends InputSplit implements Writable{
private Path file; //文件路径
private long start; //分片起始位置
private long length; //分片长度
private String[] hosts; //存储分片的hosts public FileSplit(Path file, long start, long length, String[] hosts) {
this.file = file;
this.start = start;
this.length = length;
this.hosts = hosts;
}
}

一个FileSplit对应Mapper的一个输入文件,不管这个文件有多么的小,也是作为一个单独的InputSplit来处理;
在输入文件是由大量小文件组成的场景下,就会有大量的InputSplit,从而需要大量的Mapper的处理;
大量的Mapper Task创建和销毁开销将是巨大的;可以采用CombineFileSplit将多个小文件进行合并再交由Mapper Task处理;

4、FileInputFormat

public List<InputSplit> getSplits(JobContext job) throws IOException {
/**
* getFormatMinSplitSize() = 1
* job.getConfiguration().getLong(SPLIT_MINSIZE, 1L)
* SPLIT_MINSIZE = "mapreduce.input.fileinputformat.split.minsize"
* mapred-default.xml中参数为0
*/
long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job)); //计算分片的最小值: max(1,0) = 1 /**
* SPLIT_MAXSIZE = "mapreduce.input.fileinputformat.split.maxsize"
* mapred-default.xml中参数为空
*/
long maxSize = getMaxSplitSize(job); //计算分片的最大值:Long.MAX_VALUE //存储输入文件的分片结果
List<InputSplit> splits = new ArrayList<InputSplit>();
List<FileStatus> files = listStatus(job);
for (FileStatus file: files) {
Path path = file.getPath();
long length = file.getLen();
if (length != 0) {
...
if (isSplitable(job, path)) { //能分片
long blockSize = file.getBlockSize();
long splitSize = computeSplitSize(blockSize, minSize, maxSize);{
//max(1, min(Long.MAX_VALUE, 64M)) = 64M 默认情况下splitSize=blockSize
return Math.max(minSize, Math.min(maxSize, blockSize));
} //循环分片,当剩余数据与分片大小比值大于Split_Slop时,继续分片,小于等于时,停止分片
long bytesRemaining = length;
while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) { //SPLIT_SLOP = 1.1
int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
splits.add(makeSplit(path, length-bytesRemaining, splitSize, blkLocations[blkIndex].getHosts()));
bytesRemaining -= splitSize;
} //处理余下的数据
if (bytesRemaining != 0) {
int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
splits.add(makeSplit(path, length-bytesRemaining, bytesRemaining, blkLocations[blkIndex].getHosts()));
}
} else { // 不可分片,整块返回(有些压缩后是不能分片处理的)
splits.add(makeSplit(path, 0, length, blkLocations[0].getHosts()));
}
} else {
splits.add(makeSplit(path, 0, length, new String[0]));
}
}
job.getConfiguration().setLong(NUM_INPUT_FILES, files.size()); // 设置输入文件数量
LOG.debug("Total # of splits: " + splits.size());
return splits;
}

5、PathFilter

protected List<FileStatus> listStatus(JobContext job) throws IOException {
......
List<PathFilter> filters = new ArrayList<PathFilter>();
filters.add(hiddenFileFilter);
PathFilter jobFilter = getInputPathFilter(job);
if (jobFilter != null) {
filters.add(jobFilter);
}
PathFilter inputFilter = new MultiPathFilter(filters);
......
}

PathFilter文件筛选器接口,使用它我们可以控制哪些文件要作为输入,哪些不作为输入;
PathFilter有一个accept(Path)方法,当接收的Path要被包含进来,就返回true,否则返回false;

public interface PathFilter {
boolean accept(Path path);
} //过滤掉文件名以_或者.开头的文件
private static final PathFilter hiddenFileFilter = new PathFilter(){
public boolean accept(Path p){
String name = p.getName();
return !name.startsWith("_") && !name.startsWith(".");
}
};

6、RecordReader

RecordReader将InputSplit拆分成KEY-VALUE对

public abstract class RecordReader<KEYIN, VALUEIN> implements Closeable {
//InputSplit初始化
public abstract void initialize(InputSplit split,TaskAttemptContext context) ; //读取分片下一个<key, value>对
public abstract boolean nextKeyValue() throws IOException, InterruptedException; //获得当前读取到的KEY
public abstract KEYIN getCurrentKey() throws IOException, InterruptedException; //获得当前读取到的VALUE
public abstract VALUEIN getCurrentValue() throws IOException, InterruptedException; //跟踪读取分片的进度
public abstract float getProgress() throws IOException, InterruptedException; //关闭RecordReader
public abstract void close() throws IOException;
}

7、Mapper

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
public abstract class Context implements MapContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> {
} //预处理,仅在map task启动时运行一次
protected void setup(Context context) throws IOException, InterruptedException {
} //对于InputSplit中的每一对<key, value>都会运行一次
protected void map(KEYIN key, VALUEIN value, Context context) throws IOException, InterruptedException {
context.write((KEYOUT) key, (VALUEOUT) value);
} //扫尾工作,比如关闭流等
protected void cleanup(Context context) throws IOException, InterruptedException {
} public void run(Context context) throws IOException, InterruptedException {
setup(context);
try {
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
} finally {
cleanup(context);
}
}
}

模板模式的应用:run方法:
1)setup
2)循环从InputSplit中获得到的KV对调用map函数进行处理
3)cleanup

至此完成了MapReduce的输入文件是如何被过滤分片读取读出“K-V对”,然后交给Mapper类来处理

MapReduce从输入文件到Mapper处理之间的过程的更多相关文章

  1. Hadoop(十七)之MapReduce作业配置与Mapper和Reducer类

    前言 前面一篇博文写的是Combiner优化MapReduce执行,也就是使用Combiner在map端执行减少reduce端的计算量. 一.作业的默认配置 MapReduce程序的默认配置 1)概述 ...

  2. Hadoop Mapreduce分区、分组、二次排序过程详解[转]

    原文地址:Hadoop Mapreduce分区.分组.二次排序过程详解[转]作者: 徐海蛟 教学用途 1.MapReduce中数据流动   (1)最简单的过程:  map - reduce   (2) ...

  3. hadoop平台上HDFS和MAPREDUCE的功能、工作原理和工作过程

    作业要求来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3319 1.用自己的话阐明Hadoop平台上HDFS和MapReduce ...

  4. 【转】wpa_supplicant与wpa_cli之间通信过程

    [转]wpa_supplicant与wpa_cli之间通信过程 转自:http://blog.chinaunix.net/uid-26585427-id-4051479.html wpa_suppli ...

  5. MapReduce的输入文件是两个

    [学习笔记] 1.对于MapReduce程序,如何输入文件是两个文件? 这一小节,我们将继续第一章大数据入门的HelloWorld例子做进一步的研究.这里,我们研究如何输入文件是两个文件.packag ...

  6. Hadoop学习笔记(老版本,YARN之前),MapReduce任务Namenode DataNode Jobtracker Tasktracker之间的关系

    一.基本概念 在MapReduce中,一个准备提交执行的应用程序称为“作业(job)”,而从一个作业划分出的运行于各个计算节点的工作单元称为“任务(task)”.此外,Hadoop提供的分布式文件系统 ...

  7. 027_编写MapReduce的模板类Mapper、Reducer和Driver

    模板类编写好后写MapReduce程序,的模板类编写好以后只需要改参数就行了,代码如下: package org.dragon.hadoop.mr.module; import java.io.IOE ...

  8. MapReduce(2): How does Mapper work

    In the previous post, we've illustrated how Hadoop MapReduce prepares input for Mappers. Long story ...

  9. 关于Mybatis与Spring整合之后SqlSession与mapper对象之间数量的问题。

    1,sqlsession的真实类型和数量 由于使用spring管理bean,当我们在代码中需要使用这个bean的时候,会首先去容器中找,第一次需要调用MapperFactoryBean的getObje ...

随机推荐

  1. openstack奠基篇:devstack (liberty)于centos 7安装

    openstack是什么,能做什么,我就不说了,他的优势和伟大,可以想想AWS的云服务平台.学习和研究openstack(IaaS),个人的习惯是有一个可以操作的平台,然后结合代码看看详细逻辑,这个过 ...

  2. IOS开发-手势简单使用及手势不响应处理办法

    1.点击 2.长按 3.拖拽 4.轻扫.捏合.旋转 5.使用手势需要注意的地方 1.注意处理轻扫和拖拽的冲突 //那个时间短的话 就让那个先执行 //处理 拖拽和轻扫 两个手势的冲突 //需要轻扫手势 ...

  3. 【LVM】LVM自动扩容脚本

    概要说明: /dev/mapper/vg0-data挂载在目录/data下: 当新增物理磁盘时,需要自动对/dev/mapper/vg0-data磁盘时进行扩容(自动化脚本): 当新增物理磁盘时,自动 ...

  4. 【转】双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    架构简介 前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构.此架构主要是由kee ...

  5. Makefile编译选项CC与CXX/CPPFLAGS、CFLAGS与CXXFLAGS/LDFLAGS

    转自:http://www.firekyrin.com/archives/597.html 编译选项 让我们先看看 Makefile 规则中的编译命令通常是怎么写的. 大多数软件包遵守如下约定俗成的规 ...

  6. 解决RPM包相互依赖的有效方法

    出自:http://blog.csdn.net/kai27ks/article/details/7473683 前言:常用RPM的朋友们都知道,RPM简单易用,但是它的依赖关系是最头疼的!有时候比方说 ...

  7. 64. Minimum Path Sum

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  8. 黄聪:PHP使用Simple_HTML_DOM遍历、过滤及保留指定属性

    <? /* * 参考资料: * http://www.phpddt.com/manual/simplehtmldom_1_5/manual_api.htm * http://www.phpddt ...

  9. JMS的常用方法

    import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; impor ...

  10. psutil模块安装指南(win与linux)

    1.windows下psutil模块安装: https://pypi.python.org/packages/3.4/p/psutil/ 下载符合版本的软件包下载,然后安装即可. 2.ubuntu下载 ...