MapReduce框架原理-InputFormat数据输入(From 尚硅谷)

个人学习整理,所有资料来自尚硅谷
B站学习连接:添加链接描述

MapReduce框架原理-InputFormat数据输入

1.1 InputFormat数据输入

1.1.1 切片与MapTask并行度决定机制

  • 问题引出

    MapTask的并行度决定Map阶段的任务处理并发度,进行影响到整个Job的处理速度。

  • MapTask并行度决定机制

    • 数据块:Block是HDFS物理上把数据分成一块一块。数据块是HDFS存储数据单位

    • 数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是MapReduce程序计算输入数据的单位,一个切片会对应启动一个MapTask。

(1)一个Job的Map阶段并行度由客户端在提交Job时的切片数决定;

(2)每一个Split切片分配一个MapTask并行实例处理;

(3)默认情况下,切片大小=BlockSize;

(4)切片时不考虑数据集整体,而是逐个针对每一个文件单独切片。

1.1.2 Job提交流程和切片解析

(1)Job提交流程
在这里插入图片描述

(2)FileInputFormat切片源码

  • 程序先找到数据存储的目录;

  • 开始遍历处理(规划切片)目录下的每一个文件

  • 遍历第一个文件ss.txt

    • 获取文件大小fs.sizeOf(ss.txt)

    • 计算切片大小

      computeSplitSize(Math.max(minSize,Math.min(maxSize,blocksize)));//blocksize=128M
      
    • 默认情况下,切片大小=blocksize

    • 开始时,形成第一个切片:ss.txt—0-128M,第二个切片:ss.txt—128-256M,第三个切片:ss.txt—256-300M(每次切片时,都需要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片

    • 将切片信息写到一个切片规划文件中

    • 整个切片的核心过程在getSplit()方法中完成

    • InputSplit只记录了切片的元数据信息,比如其实位置,长度以及所在的节点列表等

  • 提交切片规划文件到YARN上,YARN上的MrAppMaster就可以根据切片规划文件计算开启MapTask个数

1.1.3 FileInputFormat切片机制

在这里插入图片描述

在这里插入图片描述

1.1.4 TextInputFormat

(1)FileInputFormat实现类

​ 在运行MapReduce程序时,输入的文件格式包括:基于行的日志文件、二进制格式文件、数据库表等。针对不同的数据类型,MapReduce是如何读取这些数据的?

​ FileInputFormat常见的接口实现类包括:TextInputFormat、KeyValueTextInputFormat、NLineInputFormat、CombineTextInputFormat和自定义InputFormat等。

(2)TextInputFormat

​ TextInputFormat是默认的FileInputFormat实现类。按行读取每条记录。键是存储该行在整个文件中的起始偏移量,LongWritable类型。值是这行的内容,不包括任何行终止符,Text类型。

1.1.5 CombineTextInputFormat切片机制

框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。

  • 应用场景:

    CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。

  • 虚拟存储切片最大值设置

    CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
    

    注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。

  • 切片机制

    生成切片过程包括:虚拟存储过程和切片过程两部分。
    在这里插入图片描述

1.1.6 CombineTextInputFormat

需求:将输入的大量小文件合并成一个切片统一处理

输入:4个小文件

输出:期望一个切片处理4个文件

(1)默认使用TextInputFormat会产生4个MapTask

  • Mapper类
package com.atguigu.mapreduce.combineTextInputformat;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * KEYIN ,map阶段输入的key的类型:(偏移量)LongWritable
 * VALUEIN,map阶段输入的value的类型:(这一行的内容)Text
 * KEYOUT,map阶段输出的key的类型:(单词类型)Text
 * VALUEOUT,map阶段输出的value的类型:(单词次数)IntWritable
 */

public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
    private Text outK = new Text();
    private IntWritable outV = new IntWritable(1);
    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        //1.获取一行信息
        String line = value.toString();

        //2.切割
        String[] words = line.split(" ");
        
        //3.循环写出
        for (String word : words) {
            outK.set(word);

            //4.写出
            context.write(outK,outV);
        }
    }
}
  • Reducer类
package com.atguigu.mapreduce.combineTextInputformat;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * KEYIN ,reduce阶段输入的key的类型:Text
 * VALUEIN,reduce阶段输入的value的类型:IntWritable
 * KEYOUT,reduce阶段输出的key的类型:Text
 * VALUEOUT,reduce阶段输出的value的类型:IntWritable
 */
//继承Reducer,org.apache.hadoop.mapreduce
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
    private IntWritable outV = new IntWritable();
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        //Iterable<IntWritable>类似以一个集合

        int sum = 0;
        //atguigu, (1,1)
        //1.累加
        for (IntWritable value : values) {
            sum += value.get();
        }

        outV.set(sum);
        //2.写出
        context.write(key,outV);
    }
}
  • Driver类
package com.atguigu.mapreduce.combineTextInputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.CombineTextInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordCountDriver {//mapreduce阶段若输出路径存在,则报错FileAlreadyExistsException
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        //1.获取job——> org.apache.hadoop.mapreduce
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        //2.设置jar包路径
        job.setJarByClass(WordCountDriver.class);

        //3.关联mapper和reducer(jar包和mapper和reducer怎么产生联系?)
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //4.设置map输出的kv类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //5.设置最终输出的kv类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //如果不设置InputFormat,它默认用的是TextInputFormat.class
        //job.setInputFormatClass(CombineTextInputFormat.class);

        //虚拟存储切片最大值设置4m
        //CombineTextInputFormat.setMaxInputSplitSize(job,4194304);

        //6.设置输入路径和输出路径
        FileInputFormat.setInputPaths(job,new Path("D:\\downloads\\hadoop-3.1.0\\data\\11_input\\inputcombinetextinputformat"));
        FileOutputFormat.setOutputPath(job,new Path("D:\\downloads\\hadoop-3.1.0\\data\\output\\outputCombine22"));

        //7.提交job
        boolean result = job.waitForCompletion(true);
        System.exit(result?0:1);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一个ReduceTask
在这里插入图片描述

(2)使用CombineTextInputFormat

  • 只更改驱动类
package com.atguigu.mapreduce.combineTextInputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.CombineTextInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordCountDriver {//mapreduce阶段若输出路径存在,则报错FileAlreadyExistsException
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        //1.获取job——> org.apache.hadoop.mapreduce
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        //2.设置jar包路径
        job.setJarByClass(WordCountDriver.class);

        //3.关联mapper和reducer(jar包和mapper和reducer怎么产生联系?)
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //4.设置map输出的kv类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //5.设置最终输出的kv类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //如果不设置InputFormat,它默认用的是TextInputFormat.class
        job.setInputFormatClass(CombineTextInputFormat.class);

        //虚拟存储切片最大值设置4m
        CombineTextInputFormat.setMaxInputSplitSize(job,4194304);

        //6.设置输入路径和输出路径
        FileInputFormat.setInputPaths(job,new Path("D:\\downloads\\hadoop-3.1.0\\data\\11_input\\inputcombinetextinputformat"));
        FileOutputFormat.setOutputPath(job,new Path("D:\\downloads\\hadoop-3.1.0\\data\\output\\outputCombine22"));

        //7.提交job
        boolean result = job.waitForCompletion(true);
        System.exit(result?0:1);
    }
}

根据计算,MapTask个数应该是3
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ReduceTask个数仍是1

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值