第七篇:經典案例:資料去重

穆晨發表於2017-05-20

需求

       去除掉海量檔案中的存在著的重複資料,並將結果輸出到單個檔案中。

       比如有檔案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程式的一個經典範例。

相關文章