從一個小的例子開始:java
Map和reduce之間的shuffle(洗牌)是將key值相同的放在一塊,sort(排序)是按照key值進行排序.例如like出現了兩次,就會把like放在一塊兒.you也是.而後根據key值進行按照字典的順序進行排序.下面我想將下面的數據按照時間進行排序,而且ID相同的在一塊.具體的數據格式:(數據簡化成以下,其實還包含其餘的一些數據)面試
6395 1473840570 6393 1473840390 6393 1473840150 6393 1473840450 6395 1473840030 6395 1473840991 6394 1473839970 6394 1473840811 6394 1473840090 ......................
第一列是ID號,第二列是Linux時間戳.想輸出的結果是:ID號相同的放在一塊,對應的Linux時間戳從小到大進行排序.在編寫代碼以前能夠想到,底層的MapReduce已經幫咱們作了一些工做:對key值相同進行彙集(shuffle洗牌).這裏是看主要是reduce部分,map部分工做已經簡化了.
剛開始的時候,我是這麼想的:
map(k0,v0)-->list(k1,v1)
key: k1 是ID號, Value: v1 是時間戳
reduce(k1,list(v1)) -->list(k2,v2)
在reduce中對list(v1),也就是時間戳列表,先添加到list中,而後用Collections的sort方法對list進行排序,最後將結果進行輸出.程序以下:架構
public class SortReducer extends Reducer<Text,LongWritable,Text,LongWritable>{ @Override protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { // TODO Auto-generated method stub List<LongWritable> queue = new ArrayList<LongWritable>(); for(LongWritable num: values) { queue.add(num); } Collections.sort(queue);//排序 //將排序結果輸出 for(LongWritable num:queue) { context.write(key, num); } } }
貌似邏輯沒有一點問題,但是結果倒是:框架
全部的時間都是同樣的.這是爲何呢?因而網上百度一番,終於找到緣由了:分佈式
reduce方法會反覆執行屢次,但key和value相關的對象只有兩個,reduce會反覆重用這兩個對象。因此若是要保存key或者value的結果,只能將其中的值取出另存或者從新clone一個對象(例如Text store = new Text(value) 或者 String a = value.toString()),而不能直接賦引用。由於引用從始至終都是指向同一個對象,你若是直接保存它們,那最後它們都指向最後一個輸入記錄。會影響最終計算結果而出錯。ide
解決方案:
String str = num.toString();
LongWritable num1 = new LongWritable(Long.parseLong(str));源碼分析
修改後的源代碼以下:性能
public class SortReducer extends Reducer<Text,LongWritable,Text,LongWritable>{ @Override protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { // TODO Auto-generated method stub List<LongWritable> queue = new ArrayList<LongWritable>(); for(LongWritable num: values) { String str = num.toString(); LongWritable num1 = new LongWritable(Long.parseLong(str)); queue.add(num1); } Collections.sort(queue); for(LongWritable num:queue) { String str = num.toString(); LongWritable num1 = new LongWritable(Long.parseLong(str)); context.write(key, num1); } } }
最終結果:學習
感興趣能夠加Java架構師羣獲取Java工程化、高性能及分佈式、高性能、深刻淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走不少的彎路的 羣..號是:855801563 對了 小白勿進 最好是有開發經驗大數據
注:加羣要求
一、具備工做經驗的,面對目前流行的技術不知從何下手,須要突破技術瓶頸的能夠加。
二、在公司待久了,過得很安逸,但跳槽時面試碰壁。須要在短期內進修、跳槽拿高薪的能夠加。
三、若是沒有工做經驗,但基礎很是紮實,對java工做機制,經常使用設計思想,經常使用java開發框架掌握熟練的,能夠加。
四、以爲本身很牛B,通常需求都能搞定。可是所學的知識點沒有系統化,很難在技術領域繼續突破的能夠加。
5.阿里Java高級大牛直播講解知識點,分享知識,多年工做經驗的梳理和總結,帶着你們全面、科學地創建本身的技術體系和技術認知!