1 序言
一直以來,我都經常問自己想去學些什麼、學了對我現在手上的工作是否會有協助?
是的,電腦行業新東西太多,如果看到牛逼人都在侃侃而談的時候,我也去瞎搞,那肯定是不理智的,耗費精力的同時,很可能也學的不夠深刻。
對于海量資料,即所謂的大資料而言,這個時代這個名詞可能是最熱們的技術之一了。但是,我們是不是真的需要去搞呢?個人覺得,如果你手上要處理的資料沒有達到“海量”的層級,那還是先放一放,真的沒啥必要去為了工作而學習之,為了研究而學習又是另一回事,且不說它。
很不幸,我手上的資料有一部分(1億數量級)已經太大,傳統的資料庫已經無法進行計算比如排序任務。這個不幸其實又是一件幸運的事情,因為,終於可以用所謂的“大資料”技術來解決。
所以,在想用一門新技術之前,最好問問自己“這麼快的一把刀,是否真的有一塊難切的肉呢”?
2 大資料的基礎知識準備
環境:若干台伺服器,當然也可以單機;只不過效率問題。
基礎:hadoop
演算法:理解經典演算法中的“分而治之”思想
對於大資料排序任務,我們需要一套hadoop的運行環境,來跑我們的排序任務。
3 terasort資源利用
其實hadoop的源碼裡例子中有一個很不錯很不錯的例子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編號依次輸出即可。
4 排序演算法思想
對于海量資料排序,其演算法思想萬劍歸宗、其義不變——分而治之。
過程簡要描述
1 資料準備階段:從hdfs目標檔案擷取待排序資料,比如
12 24 11 60 23 46 79 1 21
2 抽樣階段:擷取桶劃分樣本,比如
11 24 46
將得到4個桶,-N~11,(11+1)~24,(24+1)~46,(46+1)~+N。N表示無窮大。
4 桶劃分(入桶)階段:將每個待排序資料按區間放入對應的桶中,比如
A桶:-N~11 ——1
B桶:(11+1)~24 ——12,24,11,23,21
C桶:(24+1)~46 ——46
D桶:(46+1)~+N ——60,79
注意桶的個數即reduce的個數。
這樣,即使我們的樣本無須,也可以很快進行桶間的排序,使得桶有序輸出。
5 桶內排序階段:對每個桶內的資料進行排序,當所有桶都排序結束時,此階段結束,所 以,如果桶均勻則此階段效率高,即樣本演算法要盡量使得劃分均勻。各個桶內的資料排 序用mapreduce進行並行排序,演算法可以根據實際需要進行選擇。總之,此階段的結果 是每個桶內的資料有序。
6 合并階段:拼接或者對桶進行桶間排序,輸出。
5 key為整數的1億條資料排序
尋找分區的代碼
/** * * @param arr * 遞增有序的桶分割點(採樣點) * @param des * 待入桶的key * @return 桶位置 */private int find(Integer[] arr, Integer des) {int low = 0; int high = arr.length-1; while(low <= high) { int middle = (low + high)/2; if(des == arr[middle]) { return middle; }else if(des <arr[middle]) { high = middle - 1; }else { low = middle + 1; } } if(low == 0) return 0; return arr[low-1]; }/** * 每個資料都會執行此函數,進行partition * * @return 返回partition的序號,比如0表示此條資料進入第0個分區 */@Overridepublic int getPartition(IntWritable key, Text value, int numPartitions) {return find(splitPoints, key.get());}
TeraSort對這1億條資料進行排序,共劃分成100000個桶TeraGen擷取1億條隨機資料,供3.4G
排序結果第一頁: