需求
去除掉海量檔案中的存在著的重複資料,並將結果輸出到單個檔案中。
比如有檔案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程式的一個經典範例。