本文連接: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
仍是
服務器
hello www.aboutyun.com
咱們在作填空題,框架以外的咱們尚未看到,因此我須要明白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
上面下載附件,上面沒有必要都放到hadoop_home/bin下面,缺什麼咱們放到裏面就ok了。咱們的路徑是eclipse
環境有了,咱們須要準備數據以及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輸出咱們想看到的內容:
這裏咱們主要驗證:value值傳遞過來究竟是什麼?
運行以後下面結果
結果分析:
<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));
一個放在循環內,一個放在了循環外,因此產生了下面的結果。這是不少初學者,在學習之初可能會碰到的問題