zoukankan      html  css  js  c++  java
  • 解读:标准输入/输出格式

    输入格式类InputFormat

    用于描述MR作业的输入规范,主要功能:输入规范检查(比如输入文件目录的检查)、对数据文件进行输入切分和从输入分块中将数据记录逐一读取出来、并转化为Map输入的键值对

    • getSplits()方法返回List<InputSplit>集合,作用是将输入文件在逻辑上划分为多个输入分片,每个分片的数据存放在List集合中。
    • createRecordReader()方法返回一个RecordReader对象,该对象用来将InputSplit解析成若干个key/value对。MR框架在Map Task执行过程中,会不断调用RecordReader对象中的方法,迭代获取key/value对并交给map()函数处理。【此方法在更为具体的子类中实现,如TextInputFormat

    FileInputFormat类

    主要功能是为子类提供统一的getSplits()方法实现。其中最核心的两个算法是:

    1).文件切分算法. 主要用于确定InputSplit的个数以及每个InputSplit对应的数据段。FileInputFormat以文件为单位切分生成各个InputSplit,对于每个文件,由三个属性值确定其对应的InputSplit的个数详见Job流程:决定map个数的因素

    2).host选择算法. 待InputSplit切分方案确定后,下一步确定每个InputSplit的元数据信息。这通常由四部分组成:<file,start,length,hosts>,分别表示InputSplit所在的文件起始位置字节长度以及所在的host(节点)列表。其中,前三项很容易确定,难点在于host列表的选择方法。

      虽然InputSplit对应的block可能位于多个节点上,但考虑到任务调度的效率,通常不会把所有节点加到InputSplit的host列表中,而是选择包含该InputSplit数据总量最大的前几个节点(默认是10个,多余的过滤掉),以作为任务调度时判断任务是否具有本地性的主要凭证。为此,FileInputFormat设计了一个简单有效的启发式算法

    1. 按照rack包含的数据量对rack进行排序
    2. 在rack内部按照每个node包含的数据量对node排序
    3. 取前N个node的host作为InputSplit的host列表,这里的N为block副本数

    例子:某个Hadoop集群的网络拓扑图如图所示,HDFS中block副本数为3,某个InputSplit包含3个block,大小依次是100、150和75,很容易计算,4个rack包含的(该InputSplit的)数据量分别是175、250、150和75。rack2中的node3和node4,rack1中的node1将被添加到该InputSplit的host列表中。

    host选择算法过程:对4个rock包含(该InputSplit的)数据量的大小进行排序:rock2 > rock1 > rock3 > rock4,所以选择 rock2 中node3和node4的file1和file2,rack1中node1的file3加载到该InputSplit的host列表中。

      从以上host选择算法可知,当InputSplit尺寸大于block尺寸时Map Task并不能实现完全数据本地性,也就是说,总有一部分数据需要从远程节点上读取,因而可以得出以下结论~:

    当使用基于FileInputFormat实现InputFormat时,为了提高Map Task的数据本地性,应尽量使InputSplit大小与block大小相同。

    TextInputFormat类

    TextInputFormat继承自FileInputFormat类,间接继承自InputFormat类。TextInputFormat类中包含两个方法:

    • isSplitable()作用是判断文件是否可以被切分成输入片
    • createRecordReader()作用是读取文件的内容,返回一个LineRecordReader类的对象

    LineRecordReader类中有一个initialize()方法,它用于对InputSplit进行初始化。类中的其他方法则是将其解析成一个个键值对输出。

    输出格式化类OutPutFormat

    OutputFormat是一个抽象类,主要用于描述输出数据的格式,将用户提供的key/value对写入特定格式的文件中。

    • getRecordWriter()方法返回一个RecordWriter类对象。该类中的write()方法接收一个key/value对,并将之写入文件。在Task执行过程中,MapReduce框架会将map()或者reduce()函数产生的结果传入write()方法。
    • checkOutputSpecs()方法在用户作业被提交到RM之前,由JobClient自动调用,以检查输出目录是否合法。
    • getOutputCommitter()方法返回一个OutputCommitter类的对象。该类是输出MR结果的提交器。

    TextOutputFormat

    FileOutputFormat类也是一个抽象类,具体的实现类在于TextOutputFormat类,其中包含一个LineRecordWriter的静态内部类,该类负责输出一行MR结果。

    • 第 48 行可以看出文本输出的时候使用 UTF-8 编码
    • 第 52 行表示换分行的符号是“ ”
    • 第 71 行的构造方法可以看出,输出键值对的默认分隔符是制表符“ ”.通过代码conf.set("mapreduce.output.textoutputformat.separator", "******");自定义输出的分隔符。

  • 相关阅读:
    android 多线程
    Uva 10881 Piotr’s Ants 蚂蚁
    LA 3708 Graveyard 墓地雕塑 NEERC 2006
    UVa 11300 Spreading the Wealth 分金币
    UVa 11729 Commando War 突击战
    UVa 11292 The Dragon of Loowater 勇者斗恶龙
    HDU 4162 Shape Number
    HDU 1869 六度分离
    HDU 1041 Computer Transformation
    利用可变参数函数清空多个数组
  • 原文地址:https://www.cnblogs.com/skyl/p/4763085.html
Copyright © 2011-2022 走看看