MapReduce 編程 系列二 Map階段實現,mapreducemap

來源:互聯網
上載者:User

MapReduce 編程 系列二 Map階段實現,mapreducemap

現在想從日誌中提取資料,記錄檔如下:

2014-05-10 13:36:40,140307000287,536dbacc4700aab274729cca,login2014-05-10 13:37:46,140310000378,536dbae74700aab274729ccb,login2014-05-10 13:39:20,140310000382,536dbb284700aab274729ccd,login2014-05-10 13:39:31,140331001080,536dbb864700aab274729ccf,login2014-05-10 13:39:45,140331001105,536dbba04700aab274729cd4,login2014-05-10 13:39:45,140328000969,536dbba04700aab274729ce4,login2014-05-10 13:39:45,140408001251,536dbba04700aab274729cd8,login2014-05-10 13:39:45,140328000991,536dbba04700aab274729ce9,login2014-05-10 13:39:45,140324000633,536dbba14700aab274729cf5,login2014-05-10 13:39:45,140331001077,536dbba04700aab274729cdd,login2014-05-10 13:39:45,140408001242,536dbba04700aab274729cd7,login2014-05-10 13:39:45,140327000941,536dbba14700aab274729cf1,login2014-05-10 13:39:45,140408001265,536dbba04700aab274729ce5,login2014-05-10 13:39:45,140324000673,536dbba04700aab274729cd3,login2014-05-10 13:39:45,140331001066,536dbba04700aab274729cd5,login2014-05-10 13:39:45,140408001292,536dbba14700aab274729cee,login2014-05-10 13:39:45,140328000966,536dbba14700aab274729cec,login2014-05-10 13:39:45,140312000501,536dbba04700aab274729ce1,login2014-05-10 13:39:45,140306000216,536dbba14700aab274729d02,login2014-05-10 13:39:45,140327000856,536dbba04700aab274729ce2,login2014-05-10 13:39:46,140328000985,536dbba14700aab274729cf7,login2014-05-10 13:39:46,140306000245,536dbba14700aab274729d0d,login2014-05-10 13:39:46,140326000797,536dbba14700aab274729cf6,login2014-05-10 13:39:46,140328000993,536dbba14700aab274729d12,login2014-05-10 13:39:46,140331001115,536dbba14700aab274729d10,login2014-05-10 13:39:46,140325000744,536dbba04700aab274729ce0,login2014-05-10 13:39:46,140328000982,536dbba14700aab274729d0a,login2014-05-10 13:39:46,140331001063,536dbba04700aab274729ce3,login2014-05-10 13:39:46,140331001067,536dbba14700aab274729d1c,login2014-05-10 13:39:46,140401001157,536dbba04700aab274729ce8,login2014-05-10 13:39:46,140408001216,536dbba14700aab274729cef,login2014-05-10 13:39:46,140401001174,536dbba14700aab274729d27,login2014-05-10 13:39:46,140306000215,536dbba04700aab274729cde,login2014-05-10 13:39:46,140331001064,536dbba04700aab274729cdc,login2014-05-10 13:39:46,140326000825,536dbba04700aab274729cd9,login2014-05-10 13:39:46,140408001294,536dbba14700aab274729d0f,login


我希望將login前面的裝置ID取出來,進行數量的統計,最後得到結果: 

各個裝置的累計登入次數

536dbba04700aab274729cdc 5
536dbba04700aab274729ce3 4

好,建立一個LogMapper類,該類負責做資料的Map,前兩各模板參數用於KeyIn和ValueIn, 後兩個模板參數用於KeyOut和ValueOut,都是代表類型。

假定一個<KeyIn, ValueIn>組成一個pair,輸入的很多pair在一個組裡面, 這些pair被一定的演算法Map之後,會變成很多組pair。

官方文檔:http://hadoop.apache.org/docs/r2.4.1/api/org/apache/hadoop/mapreduce/Mapper.html

Maps input key/value pairs to a set of intermediate key/value pairs.
注意,這裡的Mapper類用的包是mapreduce,以前有一個老的叫mapred。

這裡介紹了兩者的區別:

http://stackoverflow.com/questions/7598422/is-it-better-to-use-the-mapred-or-the-mapreduce-package-to-create-a-hadoop-job


LongWritable和IntWritable是兩個類,用於協助建立可以Long和Int類型的變數。它們能夠協助將Long和Int的值序列化成位元組流,因此都有兩個關鍵方法讀入和寫出:

 void readFields(DataInput in) 
          Deserialize the fields of this object from in.
   
 void write(DataOutput out) 
          Serialize the fields of this object to out.

這個和Hadoop內部RPC調用時採用的序列化演算法有關。

我的Mapper代碼:

package org.freebird.mapper;import java.io.IOException;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Mapper;/**                                                                                                                                                * Describe class LogMapper here.                                                                                                                  *                                                                                                                                                 *                                                                                                                                                 * Created: Wed Sep 24 15:14:17 2014                                                                                                               *                                                                                                                                                 * @author <a href="mailto:chenshu@letv.com"></a>                                                                                                  * @version 1.0                                                                                                                                    */public class LogMapper    extends Mapper<LongWritable, Text, Text, IntWritable> {    private final static IntWritable ONE = new IntWritable(1);    public void map(Object key, Text value, org.apache.hadoop.mapreduce.Mapper.Context ctx) throws IOException, InterruptedException {        String[] line = value.toString().split(",");        if (line.length == 4) {            String dId = line[2];            ctx.write(new Text(dId), ONE);        }    }}


這個Mapper的子類覆蓋了map函數,將字串用,號拆開後,取出第三個元素作為裝置ID, 然後作為key寫入context對象。

這裡value設定為1, 因為後面reduce階段會簡單的求和。

Context類文檔參考: http://hadoop.apache.org/docs/r1.1.1/api/org/apache/hadoop/mapreduce/Mapper.Context.html

write方法不是一般概念的hasmap添加key,value,而是產生一個新的pair對象,裡麵包含了key和value。 如果多個key相同,也會產生多個pair對象,交給reduce階段處理。


基本流程是, 架構會使用FileInputFormat讀取檔案,預設會根據檔案大小的進行記錄拆分,這裡拆分器叫做InputSplitter。通過InputSplitter將檔案拆成若干塊,後面也就有若干個mapper與之對應。

InputSplitter裡面使用RecordReader對檔案快的記錄進行讀取,產生key/value的pair,調用mapper的map函數去處理。

當然這些流程中有些可以定製,比如InputSplitter的演算法可以修改,RecordReader也是可以定製。

而且還有一個非常有效方法,可以避免mapper將過多的資料傳遞給reducer。

比如前面的例子都是1, 其實可以先用一個HashMap對key做分組,有則value加1, 無則添加到HashMap中。

最後將分組統計後的key/value資料通過context.write方法發送給reducer,能夠大大提高效率。





Mapreduce模型為何要分成map與reduce兩個階段?是為了任務的分配的細粒度?

是為了實現分散式運算,提高計算效率。
個人覺得一個需要處理大量資料集的任務,如果想提高計算效率,可以將任務分成多個小部分來進行,每個部分處理一部分資料,就像hadoop的map任務一樣,但是很多情況下需要都是整個資料集進行計算操作,單單的分成每個單獨的小部分雖然能提高計算效率,但是導致無法完成實際需求,是沒有任何意義的,所以添加一個reduce階段,負責將分成多個部分計算的結果匯總進行處理,使得更加的滿足一般需求。當然這也不是萬能的,很多情況下還是無法滿足實際需求。這就是hadoop不是萬能的原因,很多問題是無法使用hadoop進行處理的。
 
mapreduce編程中map函數使用hadoop檔案操作api出錯

你看日誌的第三行,你的job的jobid是job_local_0001說明你的job是在本地啟動並執行,並不是在分布式環境下,但是你的url是hdfs://master:9000/說明你是在hdfs上建立檔案。這個問題說明當job運行在local環境下時不能操作hdfs。
解決方案:把你的項目打包成jar檔案,提交叢集運行即可,或者把uri的scheme改成file:///也可以,但是此時檔案是建立在本地
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.