2015-09-27 83 views
3

在我減速的代碼,我使用這個代碼片斷來概括值:Hadoop的 - 經典的MapReduce WORDCOUNT

for(IntWritable val : values) { 
    sum += val.get();   
} 

正如上面所說的給了我預期的輸出,我試圖改變代碼:

for(IntWritable val : values) { 
    sum += 1; 
} 

任何人都可以請解釋什麼是它使差異,當我在減速,而不是sum += val.get()使用sum += 1?爲什麼它給了我相同的輸出?是否有任何與合,因爲當我用這個相同的減速機代碼合成器,類輸出是不正確的用出1

映射代碼的計數的所有字:

public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { 

     String line = value.toString(); 
     StringTokenizer token = new StringTokenizer(line); 

     while(token.hasMoreTokens()) { 
      word.set(token.nextToken()); 
      context.write(word, new IntWritable(1)); 
     } 
    } 

減速器代號:

public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { 

     int sum = 0; 

     for(IntWritable val : values) { 
      //sum += val.get(); 
      sum += 1; 
     } 
     context.write(key, new IntWritable(sum)); 
    } 

驅動代碼:

job.setJarByClass(WordCountWithCombiner.class); 
     //job.setJobName("WordCount"); 

     job.setMapperClass(WordCountMapper.class); 
     job.setCombinerClass(WordCountReducer.class); 
     job.setReducerClass(WordCountReducer.class); 

     FileInputFormat.addInputPath(job, new Path(args[0])); 
     FileOutputFormat.setOutputPath(job, new Path(args[1])); 

     job.setMapOutputKeyClass(Text.class); 
     job.setMapOutputValueClass(IntWritable.class); 

     job.setOutputKeyClass(Text.class); 
     job.setOutputValueClass(IntWritable.class); 

輸入 - 「要或不要是」

預期輸出 - (是,2),(對,2),(或1),(沒有,1)

但是輸出我得到爲 - (是,1),( (或1),(不是,1)

回答

1

任何人都可以請解釋當我在減速器中使用sum += 1而不是sum += val.get()時,它會產生什麼樣的差別?

這兩個語句都在執行加法操作。首先你要計算for-loop運行的次數。在後面,你實際上正在做一個總和操作,對於給定的key,每個val對象返回的int值。

爲什麼它給了我相同的輸出?它與Combiner有什麼關係嗎?

答案是是的。這是因爲Combiner

現在讓我們來看看您傳遞的輸入,這將僅實例化一個Mapper。所述Mapper的輸出是:

(to,1), (be,1), (or,1), (not,1), (to,1), (be,1) 

當此轉到Combiner,基本上是相同的邏輯Reducer。輸出將是:

(be,2) , (to,2) , (or,1) , (not,1) 

現在的Combiner上述輸出變爲Reducer,它將執行和操作。然而,你定義它。所以,如果你的邏輯是sum += 1那麼輸出將是:

(be,1) , (to,1) , (or,1) , (not,1) 

但是如果你的邏輯是sum += val.get()那麼你的輸出將是:

(be,2) , (to,2) , (or,1) , (not,1) 

我希望你現在明白了吧。 CombinerReducer的邏輯是相同的,但是來到它們處理的輸入是不同的

+1

很好解釋。謝謝。 –

0

val.get();返回int所以基本上兩個代碼都是相同的。我們使用val.get()的原因取決於我們試圖解決的問題。根據你的情況,我們確信,在映射每個字地發射鍵和值1,所以在減速,你可以肯定的是val.get()將始終返回1.因此,硬編碼的整數值1給出了相同的結果。

而且使用相同的減速機的組合功能,應該不會造成任何問題。其中一個場景的輸出是將所有單詞賦予計數爲「1」的時候,將減速器的數量設置爲0,並將映射器輸出寫入輸出路徑。

+0

感謝帕布,但我仍然與Combiner部分混淆 – AJm

+0

我現在已經添加了我的大部分代碼。正如你可以在Reducer Part中看到的那樣,我已經評論了實際的代碼「sum + = val.get()」並且嘗試了「sum + = 1」。 當我執行代碼 - sum + = val.get() - 隨着Combiner和Reducer我得到適當的預期輸出。 但是當我用::: sum + = 1 :::與Combiner&Reducer一起運行代碼時,我將所有單詞(這是不正確的)的計數設置爲'1' – AJm

+0

我嘗試了MR程序並且您是對的,當我們設置一個組合器並且在reduce函數中我們使用'sum + = 1'我將所有單詞統計爲'1'。這很奇怪,也讓我感到困惑。所以到現在爲止我甚至都在尋找解決這個問題的方法。 –

1

一切都取決於sum += val.get();

值。如果總是val.get()回報,則sum += val.get();sum += 1;一樣,因爲它是在你的減速發生。

BUT

combainer是用來做預聚合在映射器側(比減速聚合類似),以前的鍵值對發送到recuder(多個)。

Hadoop框架不保證該組合由映射器執行的時間,這將取決於映射器的輸出的數量。然後,如果只有一次執行組合,在映射器側的聚集將是確定,但在減速而不是隻接受1的很可能會收到其他號碼(val.get() >= 1)。如果在縮減器中使用sum += 1;,則會丟失映射器中的聚合數字,從而產生錯誤的輸出。

如果組合器在Mapper方面執行多次,那麼你可以想象問題可能更糟。

綜上所述,sum += 1;只能當且僅當被執行的語句只一次每個鍵值。使用組合器,這不是保證。