第七篇:经典案例:数据去重

需求

去除掉海量文件中的存在着的重复数据,并将结果输出到单个文件中。

比如有文件1中有以下数据:

hello

my

name

文件2中有以下数据

my

name

is

文件3中有以下数据

name

is

fangmeng

那么结果文件的内容应当如下(顺序不保证一致):

hello

my

name

is

fangmeng  

方案制定

Map阶段

1. 获取到输入后,按照默认原则切分输入。

2. 将切分后的value设置为map中间输出的key,而map中间输出的value为空值。

Shuffle阶段让具有相同的key的map中间输出汇集到同一个reduce节点上

Reduce阶段

将获取到的键值对的第一个键取出,作为reduce输出的键,值依然为空,或者你也可以输出键值对的个数。

注意是第一个键。因为会传递过来很多键值对 - 他们都有同样的键,只用选取第一个键就够了。

这和其他案例中需要依次遍历Shuffle阶段传递过来的中间键值对进行计算的模式是不同的。

代码示例

 1 package org.apache.hadoop.examples;
 2
 3 import java.io.IOException;
 4
 5 //导入各种Hadoop包
 6 import org.apache.hadoop.conf.Configuration;
 7 import org.apache.hadoop.fs.Path;
 8 import org.apache.hadoop.io.Text;
 9 import org.apache.hadoop.mapreduce.Job;
10 import org.apache.hadoop.mapreduce.Mapper;
11 import org.apache.hadoop.mapreduce.Reducer;
12 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
13 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
14 import org.apache.hadoop.util.GenericOptionsParser;
15
16 // 主类
17 public class Dedup {
18
19     // Mapper类
20     public static class Map extends Mapper<Object, Text, Text, Text>{
21
22         // new一个值为空的Text对象
23         private static Text line = new Text();
24
25         // 实现map函数
26         public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
27
28             // 将切分后的value作为中间输出的key
29             line = value;
30             context.write(line, new Text(""));
31         }
32     }
33
34     // Reducer类
35     public static class Reduce extends Reducer<Text,Text,Text,Text> {
36
37         // 实现reduce函数
38         public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
39
40             // 仅仅输出第一个Key
41             context.write(key, new Text(""));
42         }
43     }
44
45     // 主函数
46     public static void main(String[] args) throws Exception {
47
48         // 获取配置参数
49         Configuration conf = new Configuration();
50         String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
51
52         // 检查命令语法
53         if (otherArgs.length != 2) {
54             System.err.println("Usage: Dedup <in> <out>");
55             System.exit(2);
56         }
57
58         // 定义作业对象
59         Job job = new Job(conf, "Dedup");
60         // 注册分布式类
61         job.setJarByClass(Dedup.class);
62         // 注册Mapper类
63         job.setMapperClass(Map.class);
64         // 注册合并类
65         job.setCombinerClass(Reduce.class);
66         // 注册Reducer类
67         job.setReducerClass(Reduce.class);
68         // 注册输出格式类
69         job.setOutputKeyClass(Text.class);
70         job.setOutputValueClass(Text.class);
71         // 设置输入输出路径
72         FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
73         FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
74
75         // 运行程序
76         System.exit(job.waitForCompletion(true) ? 0 : 1);
77     }
78 }

运行结果

小结

去重在日志分析中有非常广泛的应用,本例也是MapReduce程序的一个经典范例。

时间: 2024-12-21 05:35:54

第七篇:经典案例:数据去重的相关文章

经典案例 - 数据去重

需求 去除掉海量文件中的存在着的重复数据,并将结果输出到单个文件中. 比如有文件1中有以下数据: hello my name 文件2中有以下数据 my name is 文件3中有以下数据 name is fangmeng 那么结果文件的内容应当如下(顺序不保证一致): hello my name is fangmeng 方案制定 Map阶段: 1. 获取到输入后,按照默认原则切分输入. 2. 将切分后的value设置为map中间输出的key,而map中间输出的value为空值. Shuffle阶

转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

秒杀多线程第七篇 经典线程同步 互斥量Mutex(续)

java使用Synchronized关键字实现互斥,而同时有Lock支持. 这两个的效果是等同的,Synchronized性能的起伏较大,而lock比较收敛. 为了代码的可读性,Synchronized更建议使用.

秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

版权声明:本文为博主原创文章,未经博主允许不得转载. 前面<秒杀多线程第四篇一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,这个问题包括了主线程与子线程的同步,子线程间的互斥,是一道非常经典的多线程同步互斥问题范例,后面分别用了四篇 <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> <秒杀多线程第八篇经典线程同步信号量Semaphore> 来

转----秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

前面<秒杀多线程第四篇一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,这个问题包括了主线程与子线程的同步,子线程间的互斥,是一道非常经典的多线程同步互斥问题范例,后面分别用了四篇 <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> <秒杀多线程第八篇经典线程同步信号量Semaphore> 来详细介绍常用的线程同步互斥机制——关键段.事件.互斥量

秒杀多线程第八篇 经典线程同步 信号量Semaphore

版权声明:本文为博主原创文章,未经博主允许不得转载. 阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore

转--- 秒杀多线程第六篇 经典线程同步 事件Event

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的“线程所有权”特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题. 首先介绍下如何使用事件.事件Event实际上是个内核对象,它的使用非常方便.下面列出一些常用的函数. 第一个 CreateEvent 函数功能:创建事件 函数原型: HANDLEC

转---秒杀多线程第八篇 经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

秒杀多线程第六篇 经典线程同步 事件Event

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题. 首先介绍下如何使用事件.事件Event实际上是个内核对象,它的使用非常方便.下面列出一些常用的函数. 第一个 CreateEvent 函数功能:创建事件 函数原