MapReduce進階:多MapReduce的鏈式模式

前言

我們不可能一直沉浸在 WordCount 的成功運行當中,就像之前學習 Java 或是其他編程語言不會着迷於 HelloWord 一樣。
前面的 WordCount 程序只有一個 Mapper 和一個 Reducer 參與,也就是說只有一個 Job 參與。而一個 Job 在通常情況下是無法滿足實際的開發需求,我們需要有更多的 Job 參與其中,並貢獻自己的力量。在 MapReduce 模塊中,有三個主要的模式:鏈式模型,併發模型和組合模型。
本文首先以最簡單的鏈式模型作爲切入,讓你瞭解在 Hadoop 中,多個 MapReduce 是如何協作完成任務的。


版權說明

著作權歸作者所有。
商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
本文作者:Q-WHai
發表日期: 2016年6月18日
本文鏈接:http://blog.csdn.net/lemon_tree12138/article/details/51706229
來源:CSDN
更多內容:分類 >> 大數據之 Hadoop


鏈式 MapReduce 模型

所謂鏈式模式,看名字就應該很好理解。這就是簡單地把幾個 Job 串聯起來就可以了。模型圖如下:
這裏寫圖片描述


示例列舉

假設有 4 個文件:

android
java
hadoop
python

內容分別爲:
android

android fragment android
java android activity map array screen
activity
map

java

java
code java
eclipse java 
java java code java
map java spring mysql jvm java

hadoop

map
reduce
ssh
mapreduce map reduce map reduce map reduce map reduce map reduce

python

python
pycharm
java dict java

承接之前 WordCount 的例子,這裏我們要演示多 MapReduce 的操作,那麼就不能只是 WordCount,所以,這裏加入一個新的需求,將單詞數以 5 個一組,分成 N 組。將同一組的單詞寫入同一行。
這樣我們就不得不再添加一個新的 Job 來處理這個問題。


邏輯實現

在邏輯實現中,我們省略了第一個 Job,也就是 WordCount 這一個模塊,如果你想要測試運行,可以先寫好 WordCount 程序。
下面的兩塊內容,分別是詞頻分組的 Mapper 跟 Reducer,代碼細節不是關鍵,且代碼的難度不大。這裏就不細述了。
FrequenciesMapper.java

public static class FrequenciesMapper extends Mapper<Object, Text, IntWritable, Text> {

    final int groupSize = 5;

    @Override
    protected void map(Object key, Text value, Mapper<Object, Text, IntWritable, Text>.Context context)
            throws IOException, InterruptedException {
        StringTokenizer tokenizer = new StringTokenizer(value.toString());
        String keyword =  tokenizer.nextToken();
        int wordCount = Integer.parseInt(tokenizer.nextToken());
        int riseCount = (wordCount + groupSize) - (wordCount + groupSize) % groupSize;

        Text valueText = new Text("[" + keyword + ":" + wordCount + "]");

        context.write(new IntWritable(riseCount), valueText);
    }
}

FrequenciesReducer.java

public static class FrequenciesReducer extends Reducer<IntWritable, Text, IntWritable, Text> {

    @Override
    protected void reduce(IntWritable key, Iterable<Text> values,
            Reducer<IntWritable, Text, IntWritable, Text>.Context context)
                    throws IOException, InterruptedException {

        if (null == values) {
            return;
        }

        boolean firstFlag = true;
        StringBuffer buffer = new StringBuffer();
        for (Text text : values) {
            buffer.append((firstFlag ? "" : ", ") + text.toString());
            firstFlag = false;
        }

        context.write(key, new Text(buffer.toString()));
    }
}

下面就是把兩個不同的 Job 串聯在一起的核心工作了。
ChainMRClient.java

public class ChainMRClient {

    private static String inputPath = "./input";
    private static String outputPath = "./output";

    public static void main(String[] args) throws Exception {
        ChainMRClient client = new ChainMRClient();

        if (args.length == 2) {
            inputPath = args[0];
            outputPath = args[1];
        }

        client.execute();
    }

    private void execute() throws Exception {
        String tmpOutputPath = outputPath + "_tmp";
        runWordCountJob(inputPath, tmpOutputPath);
        runFrequenciesJob(tmpOutputPath, outputPath);
    }

    private int runWordCountJob(String inputPath, String outputPath) throws Exception {
        Configuration configuration = new Configuration();

        ( ... 此處省略 N 行 ... )

        return job.waitForCompletion(true) ? 0 : 1;
    }

    private int runFrequenciesJob(String inputPath, String outputPath) throws Exception {
        Configuration configuration = new Configuration();

        ( ... 此處省略 N 行 ... )

        return job.waitForCompletion(true) ? 0 : 1;
    }
}

省略部分可以參考之前的 WordCount 代碼。
在上面的代碼中,可以看到 execute() 方法中先計算了中間的輸出目錄。這樣,第一個 Job 就可以將結果輸出到這個目錄下,而不是我們向程序傳入的 outputPath 了;然後,再把這個中間輸出目錄作爲第二個 Job 的輸入目錄。
因爲是串聯,所以只要把這兩個 Job 放在代碼中合適位置串聯就可以了。


結果展示

中間結果

中間結果也就是前面的 WordCount 的結果,如下:

activity    2
android 3
array   1
code    2
dict    1
eclipse 1
fragment    1
java    11
jvm 1
map 9
mapreduce   1
mysql   1
pycharm 1
python  1
reduce  6
screen  1
spring  1
ssh 1

最終結果

可以看到在最終的結果裏,單詞已經被統計好詞頻,並進行了分組。如下:

5   [ssh:1], [spring:1], [screen:1], [python:1], [pycharm:1], [mysql:1], [mapreduce:1], [jvm:1], [fragment:1], [eclipse:1], [dict:1], [code:2], [array:1], [android:3], [activity:2]
10  [reduce:6], [map:9]
15  [java:11]

串聯 Job

這裏展示的就是剛剛運行成功的兩個 Job。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章