MapReduce-分組取TopN

MR是大數據技術中的基本功。MR源碼分析的目的是清楚一個MR Job其中有哪些細節。經過一個分組取TopN的例子來串一遍全部細節,而且培養大數據計算編程手感java

任務描述

以下數據,求出每月溫度最高的兩天。注意:數據中有垃圾數據(重複日期的數據)編程

年月日 溫度
2019-06-01 32
2019-06-02 36
2019-06-03 33
2019-05-01 32
2019-05-02 34
2019-05-03 34
2019-04-02 29
2019-04-02 24
2019-04-22 31
2019-04-22 30
複製代碼

解決思路

1.直接按年月爲key,日期和溫度做爲value

  • 這樣實現起來很簡單,map只用把年月弄成key,剩下的交給reduce來作。
  • 因爲咱們沒有干涉任務的任何配置項。分區是hash,天然相同年月的會在一塊兒。排序比較器和分組比較器都是根據key的邏輯來的。
  • 在reduce中拿到的values是日期和溫度。須要進一步設計邏輯來求解。

這種解法沒有利用MR排序的特性。 bash

2.充分利用MR排序的特性

  • 將年月日溫度做爲key
  • 切記mr很是靈活。年月日做爲key能夠再自定義排序比較器
  • 自定義排序比較器,排序邏輯爲年月溫度,溫度倒序
  • 若是不自定義分組比較器,這樣到reduce的數據不成組,由此須要自定義分組比較器,邏輯爲:相同的年月就是一組。
  • 這樣進入reduce的數據 已是相同年月,而且溫度倒序的
  • 最後在reduce只須要作一件事兒,就是看迭代出的第二筆數據和第一筆日期是否相同,相同則是垃圾數據。

自定義key

思考:這裏設置的排序邏輯和自定義排序比較器有什麼關係呢?ide

public class MyKey implements WritableComparable<MyKey> {
    private int year;
    private int month;
    private int day;
    private int wd;
    // 此處須要實現序列化相關代碼
    // 須要實現排序邏輯
}
複製代碼

自定義排序比較器

思考:和上面key的排序有什麼關係源碼分析

/** * 比較邏輯,年月溫度,且溫度 倒序 */
@Override
public int compare(WritableComparable a, WritableComparable b) {
    MyKey i = (MyKey) a;
    MyKey j = (MyKey) b;
    int c1 = Integer.compare(i.getYear(), j.getYear());
    if (c1 == 0) {
        int c2 = Integer.compare(i.getMonth(), j.getMonth());
        if (c2 == 0) {
            // 這是倒序
            return Integer.compare(j.getWd(), i.getWd());
        }
        return c2;
    }
    return c1;
}
複製代碼

自定義分區器

/** * 分區邏輯,以年月來做爲標準 * * @author huoguangyao */
public class MyPartitioner extends Partitioner<MyKey, IntWritable> {
    @Override
    public int getPartition(MyKey myKey, IntWritable intWritable, int numPartitions) {
        return Objects.hashCode(myKey.getYear() + myKey.getMonth());
    }
}
複製代碼

自定義分組比較器

相同年月的到一個分組。這樣相同年月的數據才能到達一個reduce中。大數據

public class MyGroupingComparator extends WritableComparator {
    MyGroupingComparator() {
        super(MyKey.class, true);
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        MyKey i = (MyKey) a;
        MyKey j = (MyKey) b;
        int c1 = Integer.compare(i.getYear(), j.getYear());
        if (c1 == 0) {
            return Integer.compare(i.getMonth(), j.getMonth());
        }
        return c1;
    }
}
複製代碼

總結

須要對mr的每一步都很是瞭解。才能知道爲何要這麼設計。kylin也用到了mr來作計算,並且這種編程思想貫穿整個大數據計算。spa

相關文章
相關標籤/搜索