• hadoop-MR-排序


    mapreduce作业提交流程:
        1、配置文件        //输入输出格式(TextInput(output)Format)
        2、job.waitforcompletion
        3、submit
        4、int map = split.size
            1)、看文件格式,textFile
                判断文件的压缩编解码器(文件名后缀),如果是压缩,则判断是否是可切割的压缩
                如果不是压缩,则肯定可切割
    
            2)、getMaxSplitSize    //最大切片默认是long的最大值
                getMinSplitSize    //最小切片默认是1
                blockSize        //块大小
            
        5、开始作业真正提交过程
            ExecutorService mapService = createMapExecutor();
            runTasks(mapRunnables, mapService, "map");        //执行MapTaskRunnables对象的run函数
    
            //map中除了partition、combiner还有sort阶段
    
            使用maptask的runNewMapper方法开始正式的map阶段
                1、根据自定义map类名,获得自定义map对象
                2、调用Mapper的run函数来运行用户自定义的map方法
                    //设置相关变量或者参数,一个map只调用一次
                    setup(context);
                    try {
                      while (context.nextKeyValue()) {
                    //使用while循环调用自定义map的方法
                    map(context.getCurrentKey(), context.getCurrentValue(), context);
                      }
                    } finally {
                      //清理过程,包括清理一些没用的k-v
                      cleanup(context);
                    }
    
            Spill:溢出    //当map中的数据超出内存空间的80%,超出的数据就会被本地化
    
            map端的输出称为IFile:key-len, value-len, key, value
            
            shuffle在调用的时候对ifile进行处理
    
        4、通过shuffle进行网络间分发,reduce的调用过程类似于map过程
    
        5、细节:FileInputFormat ====> RecordReader ==> 
             map ===> partition ===> sort ===> combiner ===> shuffle ====> 
             reduce ===> RecordWriter ====> FileOutputFormat
    
    MR的数据倾斜处理:
        大量数据涌入单个节点,造成单个节点的负载量变大
        1、重新设计key
        2、随机分区
    
        均使用两个job
    
    
    排序:
        部分排序:对每个分区中的key分别进行排序
    
        全排序:  对所有分区中的key进行排序
             1、使用一个reduce
             2、自定义分区函数    
             3、采样        //设置采样路径,要放在输入输出路径之后
                        //保证map的输入key和输出key一致!!!
                        
                        
                如果有n个reduce,那么对应的会产生n-1个key集
    
                1)随机采样                随机取得样本
                    //freq :每个key被选中的几率    样本数/总数< freq 则继续
                    //numSamples:获得样本总数
                    //maxSplitsSampled: 最大切片数
                    //只要一个条件成立则停止采样
                    RandomSampler(double freq, int numSamples, int maxSplitsSampled)
                    
                2)间隔采样:适用场景(key有序的情况)    每隔一个相等的间隔对样本进行采样
                    //freq :每个key被选中的几率
                    //maxSplitsSampled: 最大切片数
                    //
    
                3)切片采样                对每个切片的数据头部取得数据
    
    
    
            采样过程代码顺序:保证全分区和采样设置在最后
                    
                1、设置输入输出路径
                2、设置输出k-v
                3、设置输入输出文件类型
                4、指定map和reduce的类
                5、任务数设置
                6、设置全分区函数
                7、设置采样器
    
    
                Configuration conf = job.getConfiguration();
                Job job = Job.getInstance();
                job.setJarByClass(App.class);
                job.setJobName("word count");
    
                // 设置输入输出路径
                FileInputFormat.addInputPath(job, new Path("D:/Temp/seq/1.seq"));
                FileOutputFormat.setOutputPath(job, new Path("D:/Temp/out"));
    
                FileSystem fs = FileSystem.get(conf);
                if (fs.exists(new Path("D:/Temp/out"))) {
                    fs.delete(new Path("D:/Temp/out"), true);
                }
                
                job.setNumReduceTasks(6);
    
                // 设置输出kv
                job.setOutputKeyClass(Text.class);
                job.setOutputValueClass(IntWritable.class);
                //设置输入类型
                job.setInputFormatClass(SequenceFileInputFormat.class);
    
                // 指定map和reduce的类
                job.setMapperClass(WCMapper.class);
                
                // 指定分区函数
                job.setPartitionerClass(TotalOrderPartitioner.class);
                TotalOrderPartitioner.setPartitionFile(conf, new Path("D:/Temp/par/par.seq"));
                
                /**
                 * freq 一个key被选中的几率
                 * numSamples 样本总数.
                 * maxSplitsSampled 一个切片检查的最大数量. 
                 */
                InputSampler.Sampler<Text, Text> sampler = new InputSampler.RandomSampler(0.1, 500,10);
                //InputSampler.Sampler<Text, Text> sampler = new InputSampler.IntervalSampler(0.1, 500);
                //InputSampler.Sampler<Text, Text> sampler = new InputSampler.SplitSampler(500,10);
                InputSampler.writePartitionFile(job, sampler);
                
                
                System.exit((job.waitForCompletion(true) ? 0 : 1));
    
    
        二次排序:对key进行全排序的基础上,对value进行排序
    
    
        当Map和Reduce的输出K-V不同时,要进行分别配置
    
            //设置reduce的输出K-V
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
    
            //设置Map输出k-v
            job.setMapOutputKeyClass(KVPair.class);
            job.setMapOutputValueClass(NullWritable.class);
    
    
        分组对比器:
            public class GroupComparator extends WritableComparator {
                protected GroupComparator() {
                super(KVPair.class,true);
                }
                //将相同年份的KVPair识别为一组
                @Override
                public int compare(WritableComparable a, WritableComparable b) {
                KVPair kv1 = (KVPair)a;
                KVPair kv2 = (KVPair)b;
    
                String year1 = kv1.getYear();
                String year2 = kv2.getYear();
                return year1.compareTo(year2);
                }
            }
        
    InputFormat OutputFormat:
    =====================================
        TextInputFormat:    文本类型,以行为单位处理,k:LongWritable, v:Text
        KeyValueTextInputFormat    k-v文本类型,以制表符为k-v的分隔,默认k-v均为text格式
    
        SequenceFileInputFormat:k-v序列文件,k-v类型以sequenceFile为主
            1、创建源文件
            2、在App中指定文件格式
                job.setInputFormatclass()
            3、对Map的输入k-v类型进行修改
                
    
        NLineInputFormat:    文本类型,以n行为单位进行处理,一次切片按照指定的行号进行切分
                    在处理一行文本数据量小的情况下可以使用,减少分发过程
                    k:LongWritable, v:Text
            
        
    
        DBInputFormat:对SQL中的数据进行数据迁移或分布式计算、k:LongWritable    v:DBWritable
    
            DBWritable:
    
                public class MyWritable implements Writable, DBWritable {
    
                     private String line;
                     
                    
                     public void write(DataOutput out) throws IOException {
                       out.writeUTF(line);
                       
                     }
                     
                     public void readFields(DataInput in) throws IOException {
                       line = in.readUTF();
                     }
                    
                     //使用ppst对数据进行写入
                     public void write(PreparedStatement statement) throws SQLException {
                       statement.setString(1, line);
                     }
                    
                     //jdbc读取数据返回的是结果集对象(ResultSet)
                     public void readFields(ResultSet resultSet) throws SQLException {
                       line = resultSet.getString(1);
                      
                     } 
                   }
            
    
    OutputFormat:
        对年度气温数据进行采样:Text x
                    SeqFile
    
        SequenceFileOutputFormat:
            在seqfile中设置压缩类型和压缩编解码器:
                SequenceFileOutputFormat.setOutputCompressionType(job, SequenceFile.CompressionType.BLOCK);
                SequenceFileOutputFormat.setOutputCompressorClass(job, Lz4Codec.class);
  • 相关阅读:
    腾讯微博
    城市左右选择添加按钮案例
    jQuery元素操作1
    动态创建表格
    五角星评论案例
    点击图片箭头回到顶部案例
    HDU1506: Largest Rectangle in a Histogram(最大子矩阵,好题动态优化左右边界)
    HDU1165: Eddy's research II(递推)
    HDU1158:Employment Planning(线性dp)
    HDU1081:To The Max(最大子矩阵,线性DP)
  • 原文地址:https://www.cnblogs.com/zyde/p/9225141.html
Copyright © 2020-2023  润新知