100億個數字中找出最大的10個
100億個數字找出最大的10個
類似:
微信10億使用者中,獲取紅包最多的前100使用者:
-
首先一點,對於海量資料處理,思路基本上是:必須分塊處理,然後再合併起來。
-
對於每一塊必須找出10個最大的數,因為第一塊中10個最大數中的最小的,可能比第二塊中10最大數中的最大的還要大。
-
分塊處理,再合併。也就是Google MapReduce 的基本思想。Google有很多的伺服器,每個伺服器又有很多的CPU,因此,100億個數分成100塊,每個伺服器處理一塊,1億個數分成100塊,每個CPU處理一塊。然後再從下往上合併。注意:分塊的時候,要保證塊與塊之間獨立,沒有依賴關係,否則不能完全並行處理,執行緒之間要互斥。另外一點,分塊處理過程中,不要有副作用,也就是不要修改原資料,否則下次計算結果就不一樣了。
-
上面講了,對於海量資料,使用多個伺服器,多個CPU可以並行,顯著提高效率。對於單個伺服器,單個CPU有沒有意義呢?
也有很大的意義。如果不分塊,相當於對100億個數字遍歷,作比較。這中間存在大量的沒有必要的比較。可以舉個例子說明,全校高一有100個班,我想找出全校前10名的同學,很傻的辦法就是,把高一100個班的同學成績都取出來,作比較,這個比較資料量太大了。應該很容易想到,班裡的第11名,不可能是全校的前10名。也就是說,不是班裡的前10名,就不可能是全校的前10名。因此,只需要把每個班裡的前10取出來,作比較就行了,這樣比較的資料量就大大地減少了。
想法:先把資料平均分到1000個節點上,每個節點上1000w資料,先掃描一遍資料,找出資料的最大最小值,然後平均分成1w個區間, 再掃一遍資料,獲得資料分佈的直方圖。然後從取值最大的區間開始往後掃,如果第一個區間裡面已經有1000+的資料,則停止;否則繼續掃下一個區間,直到找到1000+的資料。當然,如果有一個區間裡面資料特別多,可以對這個區間進一步細分,計算出該區間的子直方圖,使用同樣的方法掃資料。最後輸出的結果應該是所有資料加上最大和最小值。這個階段就是map階段。
這些資料匯聚起來之後,應該會剩下差不多十幾或者幾十萬資料,可以單機計算了,也就是reduce階段。對匯聚的資料進行處理時,可以先用最大最小值進行區間比較,提高效率。當然,也可以直接用最大堆演算法進行處理。
另外,如果剩下的資料較多,比如說100w+,可以重複上面的map方法,只要保證分到每個節點上的資料大於1000就行。
如果需要多次map處理,最好用spark的流式處理,hadoop比較適合一次map-reduce的操作。
————————————————
版權宣告:本文為CSDN博主「nameix」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/nameix/article/details/52016698