MapReduce Terasort算法分析

1.概述

1TB排序通常用於衡量分佈式數據處理框架的數據處理能力。Terasort是Hadoop中的的一個排序作業,在2008年,Hadoop在1TB排序基準評估中贏得第一名,耗時209秒。那麼Terasort在Hadoop中是怎樣實現的呢?本文主要從算法設計角度分析Terasort作業。

2.算法思想

實際上,當我們要把傳統的串行排序算法設計成並行的排序算法時,通常會想到分而治之的策略,即:把要排序的數據劃成M個數據塊(可以用Hash的方法做到),然後每個map task對一個數據塊進行局部排序,之後,一個reduce task對所有數據進行全排序。這種設計思路可以保證在map階段並行度很高,但在reduce階段完全沒有並行。
terasort算法簡介圖
爲了提高reduce階段的並行度,TeraSort作業對以上算法進行改進:在map階段,每個map task都會將數據劃分成R個數據塊(R爲reduce task個數),其中第i(i>0)個數據塊的所有數據都會比第i+1箇中的數據大;在reduce階段,第i個reduce task處理(進行排序)所有map task的第i塊,這樣第i個reduce task產生的結果均會比第i+1個大,最後將1~R個reduce task的排序結果順序輸出,即爲最終的排序結果。
在這裏插入圖片描述
這種設計思路很明顯比第一種要高效,但實現難度較大,它需要解決以下兩個技術難點:第一,如何確定每個map task數據的R個數據塊的範圍? 第二,對於某條數據,如果快速的確定它屬於哪個數據塊?答案分別爲【採樣】和【trie樹】。
 trie樹

3.Terasort算法

①Terasort算法流程

對於Hadoop的Terasort排序算法,主要由3步組成:採樣 –>> map task對於數據記錄做標記 –>> reduce task進行局部排序。
數據採樣在JobClient端進行,首先從輸入數據中抽取一部分數據,將這些數據進行排序,然後將它們劃分成R個數據塊,找出每個數據塊的數據上限和下線(稱爲“分割點”),並將這些分割點保存到分佈式緩存中。

在map階段,每個map task首先從分佈式緩存中讀取分割點,並對這些分割點建立trie樹(兩層trie樹,樹的葉子節點上保存有該節點對應的reduce task編號)。然後正式開始處理數據,對於每條數據,在trie樹中查找它屬於的reduce task的編號,並保存起來。

在reduce階段,每個reduce task從每個map task中讀取其對應的數據進行局部排序,最後將reduce task處理後結果按reduce task編號依次輸出即可。


② Terasort算法關鍵點
a) 採樣

Hadoop自帶了很多數據採樣工具,包括IntercalSmapler,RandomSampler,SplitSampler等(具體見org.apache.hadoop.mapred.lib)。

採樣數據條數:sampleSize = conf.getLong(“terasort.partitions.sample”, 100000);
選取的split個數:samples = Math.min(10, splits.length); splits是所有split組成的數組。
每個split提取的數據條數:recordsPerSample = sampleSize / samples;

對採樣的數據進行全排序,將獲取的“分割點”寫到文件_partition.lst中,並將它存放到分佈式緩存區中。
舉例說明:比如採樣數據爲b,abc,abd,bcd,abcd,efg,hii,afd,rrr,mnk
經排序後,得到:abc,abcd,abd,afd,b,bcd,efg,hii,mnk,rrr
如果reduce task個數爲4,則分割點爲:abd,bcd,mnk

b)map task對數據記錄做標記

每個map task從文件_partition.lst讀取分割點,並創建trie樹(假設是2-trie,即組織利用前兩個字節)。

Map task從split中一條一條讀取數據,並通過trie樹查找每條記錄所對應的reduce task編號。比如:abg對應第二個reduce task, mnz對應第四個reduce task。
在這裏插入圖片描述

c)reduce task進行局部排序

每個reduce task進行局部排序,依次輸出結果即可。


③ Terasort源代碼
e) 源碼位置
/local/zkl/hadoop/hadoop-0.20.1/hadoop-0.20.1/src/examples/org/apache/hadoop/examples/terasort
f) 下面程序是一段關於樹節點的源代碼:
			/*
  			 * A leaf trie node that does string compares to figure out where the given
             * key belongs between lower..upper.
             */
            static class LeafTrieNode extends TrieNode {
              int lower;
              int upper;
              Text[] splitPoints;
              LeafTrieNode(int level, Text[] splitPoints, int lower, int upper) {
                super(level);
                this.splitPoints = splitPoints;
                this.lower = lower;
                this.upper = upper;
              }
              int findPartition(Text key) {
                for(int i=lower; i<upper; ++i) {
                  if (splitPoints[i].compareTo(key) >= 0) {
                    return i;
                  }
                }
                return upper;
              }
              void print(PrintStream strm) throws IOException {
                for(int i = 0; i < 2*getLevel(); ++i) {
                  strm.print(' ');
                }
                strm.print(lower);
                strm.print(", ");
                strm.println(upper);
              }
            }

==================================
轉載自 基於Hadoop的大規模數據排序算法


青冥有曉月

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