用户提交 MapReduce 作业后,JobClient 会调用 InputFormat 的 getSplit方法 生成 InputSplit 的信息。
    一个 MapReduce 任务可以有多个 Split,其用于分割用户的数据源,根据用户设定的切割大小把数据源切割成 InputSplit元数据和 InputSplit原始数据。
元数据的作用:被JobTracker使用,生成Task的本地行的数据结构。
原始数据的作用:被Map Task初始化时使用,用来获取要处理的数据。
以下开始对  class JobSplit 类进行分析:
一开始就加载meta的头信息,主要用于构成Task列表的HEAD信息
static {
try {
META_SPLIT_FILE_HEADER = "META-SPL".getBytes("UTF-8");
} catch (UnsupportedEncodingException u) {
throw new RuntimeException(u);
}
}
 
2、New一个用于保存InputSplit元信息的数据结构
public static final TaskSplitMetaInfo EMPTY_TASK_SPLIT = new TaskSplitMetaInfo();
 
JobSplit 封装了读写InputSplit相关的基础类。
1、SplitMetaInfo 
首先,对于一个Job任务来说,会有一个 job.split 文件保存所有被Split后的InputSplit 的 SplitMetaInfo 属性: 
private long startOffset:该InputSplit在job.split文件中的偏移量
private long inputDataLength:该 InputSplit 的长度
private String[] locations:该 InputSplit 所在的host 列表
从这三个属性可以使TaskTracker知道从哪里读取对应的元数据并得到真正的原始数据来处理。  
    
在 SplitMetaInfo 类中,两个比较重要的函数是 readFields(反序列化) 和 write(序列化) 。如下:
public void readFields(DataInput in) throws IOException {
int len = WritableUtils.readVInt(in);
locations = new String[len];
for (int i = 0; i < locations.length; i++) {
locations[i] = Text.readString(in);
}
startOffset = WritableUtils.readVLong(in);
inputDataLength = WritableUtils.readVLong(in);
}
public void write(DataOutput out) throws IOException {
WritableUtils.writeVInt(out, locations.length);
for (int i = 0; i < locations.length; i++) {
Text.writeString(out, locations[i]);
}
WritableUtils.writeVLong(out, startOffset);
WritableUtils.writeVLong(out, inputDataLength);
}
    在分析这两个函数之前,先简单复习序列化和反序列化的定义:
  把对象转换为字节序列的过程称为对象的序列化;
  把字节序列恢复为对象的过程称为对象的反序列化。
    对象的序列化主要有两种用途:1)把对象的字节序列永久地存储在硬盘上,一般是文件。2)在网络上传送对象的字节序列。
 
接着通过查看源码,很容易会发现 public static class SplitMetaInfo implements Writable  继承了 Writable 接口,并且进入Writable 类查看得知,只要重写 Writable  就能我们自己自定义 Split 出 InputSplit的格式。
public interface Writable {
/**
* Serialize the fields of this object to <code>out</code>.
*
* @param out <code>DataOuput</code> to serialize this object into.
* @throws IOException
*/
void write(DataOutput out) throws IOException;
/**
* Deserialize the fields of this object from <code>in</code>.
*
* <p>For efficiency, implementations should attempt to re-use storage in the
* existing object where possible.</p>
*
* @param in <code>DataInput</code> to deseriablize this object from.
* @throws IOException
*/
void readFields(DataInput in) throws IOException;
 
下面再来看看 WritableUtils (可写的工具类)这个类。
由图可以知道,这个类主要是一些IO输入输出处理的函数,有兴趣的童鞋请自行查看,在此略过了。总的来说,这两个函数主要是用于把数据序列化存储为文件永久保存在硬盘和读入数据时先把文件里的字节格式的数据先转换成对象格式。
 
2、TaskSplitMetaInfo
    用于保存InputSplit元数据的数据结构。
    其包括三个属性:
private TaskSplitIndex splitIndex:Split元信息在 jib.split 文件中的位置
private long inputDataLength:InputSplit的数据长度
private String[] locations:InputSplit所在的host列表
    这三个信息是在作业初始化时,JobTracker从文件 job. splitmetainfo 文件获得的。其中,host列表信息是任务调度判断任务是否在本地的最重要因素。为什么需要这个?一切是为了提高效率,节省集群的资源开销。因为在集群中,为了容灾容错,数据一般是有多份备份的,每次TaskTracker要获取数据处理时,为了提高工作效率,都是尽可能的从本地获取数据,如果本地没有想要的数据备份时才会从本地机架的不同节点获取,再或者从不同机架的节点获取数据。
 
3、TaskSplitIndex
    用于在JobTracker向TaskTracker分配新任务时, 指定新任务待处理数据位置信息在文件 jib.split中的索引。
    其包括两个属性:
private String splitLocation:job.split文件的位置
private long startOffset:InputSplit在 job.split 文件中的位置
public void readFields(DataInput in) throws IOException {
splitLocation = Text.readString(in);
startOffset = WritableUtils.readVLong(in);
}
public void write(DataOutput out) throws IOException {
Text.writeString(out, splitLocation);
WritableUtils.writeVLong(out, startOffset);
}
 
最后,JobSplit 包含的三个与Split相关的基础类,规定了如何Split出元数据和原始数据,并且构造了一个Task Split的存储列表供TaskTracker查询,因此知道从哪里得到数据来处理。

Hadoop源码分析之产生InputSplit文件过程的更多相关文章

  1. hadoop源码分析(2):Map-Reduce的过程解析

    一.客户端 Map-Reduce的过程首先是由客户端提交一个任务开始的. 提交任务主要是通过JobClient.runJob(JobConf)静态函数实现的: public static Runnin ...

  2. Hadoop源码分析(1):HDFS读写过程解析

    一.文件的打开 1.1.客户端 HDFS打开一个文件,需要在客户端调用DistributedFileSystem.open(Path f, int bufferSize),其实现为: public F ...

  3. Hadoop源码分析之数据节点的握手,注册,上报数据块和心跳

    转自:http://www.it165.net/admin/html/201402/2382.html 在上一篇文章Hadoop源码分析之DataNode的启动与停止中分析了DataNode节点的启动 ...

  4. angular源码分析:injector.js文件分析——angular中的依赖注入式如何实现的(续)

    昨天晚上写完angular源码分析:angular中jqLite的实现--你可以丢掉jQuery了,给今天定了一个题angular源码分析:injector.js文件,以及angular的加载流程,但 ...

  5. SpringBoot源码分析之SpringBoot的启动过程

    SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30   |   分类于 springboot  |   0 Comments  |   阅读次数 SpringB ...

  6. Envoy 源码分析--程序启动过程

    目录 Envoy 源码分析--程序启动过程 初始化 main 入口 MainCommon 初始化 服务 InstanceImpl 初始化 启动 main 启动入口 服务启动流程 LDS 服务启动流程 ...

  7. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

  8. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  9. Hadoop源码分析之Configuration

    转自:http://www.it165.net/admin/html/201312/2178.html org.apache.hadoop.conf.Configuration类是Hadoop所有功能 ...

随机推荐

  1. iOS消息转发机制

    iOS消息转发机制 “消息派发系统”(message-dispatch system) 若想令类能够理解某条消息,我们必须实现出对应的方法才行.但是,在编译器向类发送其无法解读的消息时并不会报错,因为 ...

  2. Celery-4.1 用户指南: Periodic Tasks (定时任务)

    简介 celery beat 是一个调度器:它以常规的时间间隔开启任务,任务将会在集群中的可用节点上运行. 默认情况下,入口项是从 beat_schedule 设置中获取,但是自定义的存储也可以使用, ...

  3. java反射专题三

    一丶调用运行时类中指定的属性 Class clazz = Person.class; //1.获取指定的属性 Field name = clazz.getField("name") ...

  4. NSThread 基本使用

    一.简介 (1)使用NSThread对象建立一个线程非常方便 (2)但是!要使用NSThread管理多个线程非常困难,不推荐使用 (3)技巧!使用[NSThreadcurrentThread]跟踪任务 ...

  5. Shell编程进阶 2.1 shell函数

    函数 vim fun.sh #!/bin/bash function mysum() { sum=$[$+$] echo $sum } a= b= mysum $a $b sh fun.sh 6 可以 ...

  6. MyBatis使用动态代理报 invalid bound statement (not found) 错

    这个问题网上大部分都说xml文件中的路径不对 或者是resources之类的问题,如果那些文章的解决方案解决不了你的问题的话,可以看一下我遇到的这种情况: 前提: mybatis-config.xml ...

  7. [poj2398]Toy Storage

    接替关键:和上题类似,输出不同,注意输入这道题需要排序. #include<cstdio> #include<cstring> #include<algorithm> ...

  8. Java-马士兵设计模式学习笔记-工厂模式-简单工厂

    一.概述 1.目标:要控制任意类型交通工具的生产模式 2.目标有两层意思(1)任意类型 (2)生产模式,所以对应的,要这两个层面上抽象(Movable,VehicleFactory),利用接口,实现多 ...

  9. GTK编程

    一.简介 GTK(GIMP Toolkit)是一套跨多种平台的图形工具包,按LGPL许可协议发布的.虽然最初是为GIMP写的,但早已发展为一个功能强大.设计灵活的通用图形库.特别是被GNOME选中使得 ...

  10. cakephp的优点

    1.接口传参非常简单,直接域名/控制器名/方法名/param1/param2