zoukankan      html  css  js  c++  java
  • MapReduce-CombineTextInputFormat 切片机制

    MapReduce 框架默认的 TextInputFormat 切片机制是对任务按文件规划切片,如果有大量小文件,就会产生大量的 MapTask,处理小文件效率非常低。

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

    CombineTextInputFormat 切片机制过程包括:虚拟存储过程和切片过程二部分
    
    假设 setMaxInputSplitSize 值为 4M,有如下四个文件
    a.txt 1.7M
    b.txt 5.1M
    c.txt 3.4M
    d.txt 6.8M
    
    (1)虚拟存储过程
    (1.1)将输入目录下所有文件大小,依次和设置的 setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。
    (1.2)如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块,当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。 1.7M < 4M 划分一块 5.1M > 4M 但是小于 2*4M 划分二块:块1=2.55M,块2=2.55M 3.4M < 4M 划分一块 6.8M > 4M 但是小于 2*4M 划分二块:块1=3.4M,块2=3.4M 最终存储的文件: 1.7M 2.55M,2.55M 3.4M 3.4M,3.4M (2)切片过程 (2.1)判断虚拟存储的文件大小是否大于 setlMaxIputSplitSize 值,大于等于则单独形成一个切片。 (2.2)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。 最终会形成3个切片: (1.7+2.55)M,(2.55+3.4)M,(34+3.4)M

    测试读取数据的方式

    控制台日志

    可以看到读取方式与 TextInputFormat  一样,k 为偏移量,v 为一行的值,按行读取

    以 WordCount 为例进行测试,测试切片数

    测试数据

    测试代码

    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.Mapper;
    import org.apache.hadoop.mapreduce.Reducer;
    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 org.apache.log4j.BasicConfigurator;
    
    import java.io.IOException;
    import java.util.StringTokenizer;
    
    public class WordCount {
    
        static {
            try {
                // 设置 HADOOP_HOME 环境变量
                System.setProperty("hadoop.home.dir", "D:/DevelopTools/hadoop-2.9.2/");
                // 日志初始化
                BasicConfigurator.configure();
                // 加载库文件
                System.load("D:/DevelopTools/hadoop-2.9.2/bin/hadoop.dll");
            } catch (UnsatisfiedLinkError e) {
                System.err.println("Native code library failed to load.
    " + e);
                System.exit(1);
            }
        }
    
        public static void main(String[] args) throws Exception {
            args = new String[]{"D:\tmp\input", "D:\tmp\456"};
            Configuration conf = new Configuration();
            Job job = Job.getInstance(conf, "word count");
            job.setJarByClass(WordCount.class);
    
            job.setMapperClass(TokenizerMapper.class);
            job.setCombinerClass(IntSumReducer.class);
            job.setReducerClass(IntSumReducer.class);
    
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
    
            // 设置 InputFormat,默认为 TextInputFormat.class
            job.setInputFormatClass(CombineTextInputFormat.class);
            // 设置最大值即可 128M
            CombineTextInputFormat.setMaxInputSplitSize(job, 1024 * 1024 * 128);
    
            FileInputFormat.addInputPath(job, new Path(args[0]));
            FileOutputFormat.setOutputPath(job, new Path(args[1]));
            System.exit(job.waitForCompletion(true) ? 0 : 1);
        }
    
        public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {
            private final static IntWritable one = new IntWritable(1);
            private Text word = new Text();
    
            @Override
            public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
                // 查看 k-v
                // System.out.println(key + "	" + value);
                StringTokenizer itr = new StringTokenizer(value.toString());
                while (itr.hasMoreTokens()) {
                    word.set(itr.nextToken());
                    context.write(word, one);
                }
            }
        }
    
        public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
            private IntWritable result = new IntWritable();
    
            @Override
            public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
                int sum = 0;
                for (IntWritable val : values) {
                    sum += val.get();
                }
                result.set(sum);
                context.write(key, result);
            }
        }
    }

    由于所有文件加起来大小都没有 128M,所以切片数为 1

  • 相关阅读:
    Go视频教程
    Mysql常用
    同步Redux
    React跨组件通讯
    React组件通讯
    React
    git生成公钥和私钥
    常用经典算法---希尔排序
    string和c_str()使用时的坑
    腾讯云python网站开发环境搭建
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10790880.html
Copyright © 2011-2022 走看看