MapReduce案例:数据去重

MapReduce 2017-01-04

实例描述

  对数据文件中的数据进行去重。数据文件中的每行都是一个数据。

数据去重

  数据去重主要是为了掌握和利用并行化思想来对数据进行有意义的筛选。统计大数据集
上的数据种类个数、从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据去重。

设计思路

  数据去重的最终目标是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。 我们自然而然会想到将同一个数据的所有记录都交给一台 reduce 机器,无论这个数据出现多少次,只要在最终结果中输出一次就可以了。具体就是 reduce 的输入应该以数据作为 key,而对 value-list 则没有要求。当 reduce 接收到一个<key, value-list>时就直接将 key 复制到输出的 key 中,并将 value 设置成空值。
  在 MapReduce 流程中, map 的输出<key, value>经过 shuffle 过程聚集成<key,
value-list>后会交给 reduce。所以从设计好的 reduce 输入可以反推出 map 的输出 key
应为数据, value 任意。继续反推, map 输出数据的 key 为数据,而在这个实例中每个
数据代表输入文件中的一行内容,所以 map 阶段要完成的任务就是在采用 Hadoop 默认的
作业输入方式之后,将 value 设置为 key,并直接输出(输出中的 value 任意)。 map 中
的结果经过 shuffle 过程之后交给 reduce。 reduce 阶段不会管每个 key 有多少个
value,它直接将输入的 key 复制为输出的 key,并输出就可以了(输出中的 value 被设
置成空了)。

测试数据:

aaa.txt

2017-3-1 a
2017-3-2 b
2017-3-3 c
2017-3-4 d
2017-3-5 a
2017-3-6 b
2017-3-7 c
2017-3-3 c

bbb.txt

2017-3-1 b
2017-3-2 a
2017-3-3 b
2017-3-4 d
2017-3-5 a
2017-3-6 c
2017-3-7 d
2017-3-3 c

程序代码

package cn.mn1024.mapreduce.dedup;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
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.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * 功能:数据去重
 * @author GuangLing_Lin
 */

@SuppressWarnings("all")
public class DedupRunner {

    private static class DedupMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
        
        private static Text field = new Text();
        
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            field = value;
            context.write(field, NullWritable.get());
        }
        
    }
    
    private static class DedupReducer extends Reducer<Text, NullWritable, Text, NullWritable> {
        
        @Override
        protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
            context.write(key, NullWritable.get());
        }
        
    }
    
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        
        // 创建本次mr程序的job实例
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        // 指定本次job运行的主类
        job.setJarByClass(DedupRunner.class);
        
        // 指定本次job的具体Mapper、Reducer实现类
        job.setMapperClass(DedupMapper.class);
        job.setReducerClass(DedupReducer.class);
        
        // 指定本次job map阶段输出数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(NullWritable.class);
        
        // 指定本次job reduce阶段输出数据类型 也就是整个mr任务的最终输出数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);
        
        // 指定本次job待处理数据的目录和程序执行完毕结果存放的目录
        FileInputFormat.setInputPaths(job, new Path("F://dedup//input"));
        FileOutputFormat.setOutputPath(job, new Path("F://dedup//output"));
        
        // 提交本次job
        boolean b = job.waitForCompletion(true);
        System.exit(b ? 0 : 1);
    }
    
}

测试结果

2017-3-1 a
2017-3-1 b
2017-3-2 a
2017-3-2 b
2017-3-3 b
2017-3-3 c
2017-3-4 d
2017-3-5 a
2017-3-6 b
2017-3-6 c
2017-3-7 c
2017-3-7 d

每一个成功的背后都有无数个无人知晓的黑夜。

因为

夜晚,是超越对手的最佳时机。

===================== 码农1024 =====================#蔺光岭#


本文由 蔺光岭 创作,采用 知识共享署名 4.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论