經過實例讓你真正明白mapreduce---填空式、分佈(分割)編程

本文連接:http://www.aboutyun.com/thread-8303-1-1.htmlphp

 

問題導讀:

1.如何在講mapreduce函數中的字符串等信息,輸出到eclipse控制檯?
2.除了使用下文方法,還有其它方法輸出到控制檯?
3.map中,系統默認接受的value值是什麼?
4.reduce輸出不是本身想要的結果,可能的緣由是什麼?





mapreduce不是很好理解,爲何?
由於咱們傳統編程,運行程序,都在本地,怎麼會跑到別的客戶端或則服務器那,總之運行程序就是一太電腦。mapreduce牛啊,他居然可讓一個程序多臺電腦一塊跑,這也是它的神奇不一樣之處,同時也讓mapreduce蒙上了一層神祕的面紗。

這裏咱們就來揭開這個面紗。

這裏難以理解的地方是什麼?它是如何分割的,如何分組、如何分區的,什麼shuffer,等等各類概念涌入初學者腦海中,而後就是雲裏霧裏、似看清、又看不清。





這裏咱們拋棄這些全部的概念,讓咱們來一個短平快、更直接、更簡單的的認識。

記得咱們在上學的時候,有一種題型是填空題,而mapreduce就是一個填空式編程。

爲何被認爲是填空式編程,由於mapreduce是一個框架,咱們所做的就是編寫map函數、reduce函數、而後驅動函數main()。

填空,讓咱們填寫的就是map、reduce函數。剩下的則是由整個mapreduce框架來完成。


首先從map函數入手

html

// map類
static class MyMapper extends
Mapper<LongWritable, Text, Text, LongWritable> {
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {


final String[] splited =  value.toString().split(" ");
org.apache.hadoop.mapreduce.Counter count= context.getCounter("map中的值value", value.toString());
count.increment(1l);

for (String word : splited) {
context.write(new Text(word), new LongWritable(1L));
// org.apache.hadoop.mapreduce.Counter count= context.getCounter("map中的值value", new Text(word).toString()+"個數"+new LongWritable(1L).toString());
// count.increment(1l);
}

}

}


咱們知道map接受了數據,那麼這個數據是是怎麼個數據??

假如咱們有下面數據java

hello  www.aboutyun.com hello word
hello hadoop
hello mapreduce


咱們map函數以下:
map(LongWritable key, Text value, Context context)
上面有三個參數,其中key是偏移量,這裏不是咱們的重點,對於Context不瞭解,能夠查看hadoop開發必讀:認識Context類的做用.
咱們這裏重點講value,這個value究竟是什麼?
apache

hello www.aboutyun.com hello word


仍是編程

hello


仍是


服務器


咱們在作填空題,框架以外的咱們尚未看到,因此我須要明白value究竟是什麼?
下面咱們開始運行程序





運行程序,這裏讓咱們犯愁了,爲何,由於在運行這個程序以前,你有環境了嗎?沒有,app

1、搭建環境
參考 新手指導:Windows上使用Eclipse遠程鏈接Hadoop進行程序開發,首先搭建環境,這裏還用到了eclipse插件,
2、插件下載
hadoop-eclipse-plugin-2.2.0.jar

連接: http://pan.baidu.com/s/1sjQ6Nnv 密碼: uvwx
更多插件:hadoop家族、strom、spark、Linux、flume等jar包、安裝包彙總下載(持續更新)

框架

3、遇到問題
環境搭建好了,咱們開發運行程序了,遇到各類問題該如何解決,可參考
Win7 Eclipse調試Centos Hadoop2.2-Mapreduce出現問題解決方案
在window中,咱們遇到最多的問題就是缺乏
1.winutils.exe
2.hadoop.dll
<ignore_js_op>

<ignore_js_op> hadoop-common-2.2.0-bin-master.zip (273.06 KB, 下載次數: 0, 售價: 2 雲幣) 

上面下載附件,上面沒有必要都放到hadoop_home/bin下面,缺什麼咱們放到裏面就ok了。咱們的路徑是eclipse

  1. D:\hadoop2\hadoop-2.2.0\bin
複製代碼






環境有了,咱們須要準備數據以及mapreduce程序

1、準備數據
首先第一步咱們上傳待分析文件:

<ignore_js_op> 

第二步:找到文件 <ignore_js_op> 


第三步:上傳成功

<ignore_js_op> 


2、mapreduce函數分析


map函數:ide

static class MyMapper extends
                        Mapper<LongWritable, Text, Text, LongWritable> {
                protected void map(LongWritable key, Text value, Context context)
                                throws IOException, InterruptedException {
                        
                        
                        final String[] splited = value.toString().split(" ");
                        org.apache.hadoop.mapreduce.Counter count= context.getCounter("map中的值value",  value.toString());
                        count.increment(1l);

                
                        for (String word : splited) {
                                context.write(new Text(word), new LongWritable(1L));

                        }

                }


咱們看到上面紅字部分他的做用是什麼,這也正是不少犯愁的地方,由於咱們想把咱們想看到的數據輸出到eclipse的控制檯,惋惜的是 System.out.println並不如咱們願,因此咱們可使用 getCounter輸出咱們想看到的內容:

  1. org.apache.hadoop.mapreduce.Counter count= context.getCounter("map中的值value", value.toString());
  2. count.increment(1l);
複製代碼

這裏咱們主要驗證:value值傳遞過來究竟是什麼?
運行以後下面結果
結果分析:


  1. map中的值value
  2.                 hello hadoop=1
  3.                 hello mapreduce=1
  4.                 hello www.aboutyun.com hello word=1
複製代碼

<ignore_js_op> 


上面咱們看到輸出數據輸出了3次,也就是說,咱們的map執行了3次,那麼咱們的原始數據是什麼狀況,看下圖:



結論:
從這裏咱們看到有多少行就有多少個map,也就是說,系統默認一行調用一個map函數,value值爲一行的數據



同理reduce也是如此:


        // reduce類
        static class MyReduce extends
                        Reducer<Text, LongWritable, Text, LongWritable> {
                @Override
                protected void reduce(Text k2, java.lang.Iterable<LongWritable> v2s,
                                Context ctx) throws java.io.IOException, InterruptedException {
                        
                        long times = 0L;
                        for (LongWritable count : v2s) {
                                times += count.get();
                                
                                
                        }
                        org.apache.hadoop.mapreduce.Counter count1= ctx.getCounter("reduce中的值"+k2.toString(), new LongWritable(times).toString());
                        count1.increment(1l);

                        ctx.write(k2, new LongWritable(times));

                }

                
        }


這裏咱們主要驗證:reduce中key出現的次數:

<ignore_js_op> 

從上面結果咱們看到
hadoop:                      1個
hello :                           4個
mapreduce:               1個
www.aboutyun.com :1個

這裏咱們並無經過mapreduce的輸出文件來查看,而是經過getCounter來實現的。
咱們來看看reduce的輸出文結果:
<ignore_js_op> 



這裏在作一個有趣的實驗:
爲何那,由於不少初學者,可能會遇到一個問題,就是reduce的輸出結果不正確,爲何會不正確,下面咱們對reduce稍微作一些改動:

static class MyReduce extends
Reducer<Text, LongWritable, Text, LongWritable> {
@Override
protected void reduce(Text k2, java.lang.Iterable<LongWritable> v2s,
Context ctx) throws java.io.IOException, InterruptedException {

long times = 0L;
for (LongWritable count : v2s) {
times += count.get();
org.apache.hadoop.mapreduce.Counter count1= ctx.getCounter("reduce中的值"+k2.toString(), new LongWritable(times).toString());
count1.increment(1l);
ctx.write(k2, new LongWritable(times));
}



}


}


咱們查看下面結果:


<ignore_js_op> 


咱們來看看reduce的輸出文結果:

<ignore_js_op> 


仔細對比咱們把


org.apache.hadoop.mapreduce.Counter count1= ctx.getCounter("reduce中的值"+k2.toString(), new LongWritable(times).toString());
count1.increment(1l);
ctx.write(k2, new LongWritable(times));

一個放在循環內,一個放在了循環外,因此產生了下面的結果。這是不少初學者,在學習之初可能會碰到的問題

相關文章
相關標籤/搜索