用户提交 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. C字符串翻转

    实现字符串翻转,思路很简单,就是首尾字符对调. void reverse(char* str){ char* p = str + strlen(str) - 1;//最后一个字符地址 char tem ...

  2. python对MySQL进行数据的插入、更新和删除之后需要commit,数据库才会真的有数据操作。(待日后更新)

    今天在尝试用下面的python代码对MySQL进行数据的插入.更新和删除时, 突然发现代码执行成功, 通过代码查询也显示数据已经插入或更新, 但是当我在MySQL客户端通过SQL语句查询时, 数据库中 ...

  3. paramiko连接方式

    链接方法: 方式一: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh. ...

  4. 问题:C#将base64转换成二进制图片;结果:c# Base64编码和图片的互相转换代码

    c# Base64编码和图片的互相转换代码 Base64编码在Web方面有很多应用,譬如在URL.电子邮件方面.网上有很多相关的资源用于提供Base64编码和其他编码的转换,.Net Framewor ...

  5. win 10 提升权限

    问题:每次打开Visual Studio 提示,需要重启以获取管理员权限 解决: 1.Win+R 2.输入:gpedit.msc 3.windows设置->安全设置->本地策略->安 ...

  6. 使用SharedPreferences接口来实现记住密码功能

    SharedPreferences接口非常适合用来存储零散的数据.这里我们用来实现记录用户名和密码的功能.在前面我用过IO流来实现记住密码的功能.那么用SharedPreferences接口会比用IO ...

  7. Jquery前端选择器

    ----------------------祖先后代选择器------------------------------ 1.祖先 后代:根据一个元素可以取得指定的所有子元素(不管中间有多少后代)$(& ...

  8. android-auto-scroll-view-pager (无限广告轮播图)

    github 地址: https://github.com/Trinea/android-auto-scroll-view-pager Gradle: compile ('cn.trinea.andr ...

  9. android中finish和system.exit方法退出的区别

    finish只是将此activity推向后台,并没有释放资源. 而system.exit则是杀死进程,会释放资源

  10. String/StringBuilder 类 统计字符串中字符出现的次数

    1.1. 训练描述:[方法.String类] 一.需求说明:定义如下字符串: String str = “javajfiewjavajfiowfjavagkljjava”; 二.请分别定义方法统计出: ...