隨着互聯網的興起,越來越多的內容被放到互聯網中,從而導致海量數據處理受到更多人的重視,尤其是在百度、騰訊等這些涉及海量數據的公司。下面我們簡單談一下關於海量數據處理的一些常用數據結構。包括哈希、bitmap、Bloom filter、堆、mapreduce、trie樹。
(1)哈希
對於哈希,相信大家都不會陌生。其基本原理不再說明,哈希的一個關鍵點是哈希函數的選擇,如何使映射結果更加均衡及沖突減少。關於哈希也有許多變種,如一致性哈希(詳見http://www.cnblogs.com/dong008259/archive/2011/11/26/2264175.html)。海量數據處理中,哈希可用於快速查找及刪除,通常需要總數據量可以放入內存中。
哈希實例:海量日志數據,提取出某日訪問百度次數最多的那個IP。
講解:IP最多為2^32個,為4G,一次放入內存中不行,可以采用分而治之的方法,先Hash(IP)/1024,將IP地址分別映射到1024個小文件中,每個文件4M,再將每個小文件中的IP放入內存中,進行hashmap,統計出出現頻率最高的那個IP,最后可以得到1024個出現高頻的IP,采用冒泡排序,可以迅速找出頻率最高的那個IP.
(2)bitmap
bitmap可謂是非常經典的海量數據處理工具,其本質是用bit數組的某一位表示某一數據,從而一個bit數組可以表示海量數據。關於bitmap詳見:http://dong008259.blog.163.com/blog/static/51645417201191083740520/。
bitmap實例:已知某個文件內包含一些電話號碼,每個號碼為8位數字,統計不同號碼的個數。
講解:8位數字最多為99,999,999,則1億個bit就可以存儲,大約為12.5MB內存。依此查詢電話號碼,若電話號碼對應的比特位為0,則置1,若已經為1,則表明前面已出現該號碼。遍歷文件完畢后,統計所有比特位為1的位數,即為不同號碼的個數。
(3)布隆過濾器(Bloom filter)
關於布隆過濾器,在前面的一篇博客中已詳細講過,詳見:http://www.cnblogs.com/dong008259/archive/2012/01/04/2311332.html。布隆過濾器的實質是由一個位數組及k個哈希函數組成,將將要映射的元素通過k次哈希映射到位數組的相應位置當中。布隆過濾器可以看做是哈希函數和bitmap的擴展,它允許有一定的錯誤。且錯誤率與位數組的個數m、哈希函數個數k及要映射的元素個數m有必然的聯系,當hash函數個數k=(ln2)*(m/n)時錯誤率最小。
布隆過濾器實例:給你A,B兩個文件,各存放50億條URL,每條URL占用64字節,內存限制是4G,讓你找出A,B文件共同的URL。
講解:50億條URL,大約有5G條,每條占用64B,則共為320G,遠遠超過內存的4G。若想把這50億條URL全部映射到內存中,可以用布隆過濾器處理。4G內存大約為320億個bit,將50億條URL若按出錯率0.01計算,大約需要650億個bit,現在為320億個bit,也是可以接受的。所以在允許有出錯率的情況下,將50億條URL映射到4G內存中,再遍歷另一個文件,若發現已經在內存中映射,則表明該URL為共有的。
(4)堆
剛接觸堆這個概念,是在數據結構中的內部排序算法中,是一種樹形選擇排序。在海量數據存儲中,堆適合解決求取數據中符合條件的某n個數,如出現頻率最大的前n個,堆可以放在內存中進行。
堆實例:有一個1G大小的一個文件,里面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。
講解:由於內存只有1M,不能將整個文件全部放入內存中。我們采取分而治之的方法,首先將1G文件中所有的詞哈希到2000個文件中,每個文件大約為500K,哈希過程必須保證相同的詞映射到同一文件中。再在每個小文件中采用trie樹或hash_map統計出現的次數。最后在維護一個容量為100的小頂堆即可。
(5)mapreduce
mapreduce是一種分布式處理,將數據划分到不同的機器上進行處理,最后再對每台機器上的結果進行整合。數據划分,結果規約。
mapreduce實例:上千萬或億數據,統計其中出現次數最多的前N個數據。
講解:首先可以根據數據值或者把數據hash后的值,將數據按照范圍划分到不同的機子,最好可以讓數據划分后可以一次讀入內存,這樣不同的機子負責處理各種的數值范圍,實際上就是map。得到結果后,各個機子只需拿出各自的出現次數最多的前N個數據,然后匯總,選出所有的數據中出現次數最多的前N個數據,這實際上就是reduce過程。
(6)trie樹
trie樹是快速查找字符串的一個很有用的工具,是一種樹形結構。適用於重復數量比較多的海量數據。詳見:http://www.cnblogs.com/dong008259/archive/2011/11/11/2244900.html
trie樹實例:1000萬個記錄(這些查詢串的重復度比較高,長度為1-255個字節,但如果除去重復后,不超過3百萬個。一個查詢串的重復度越高,說明查詢它的用戶越多,也就是越熱門。),請你統計最熱門的10個查詢串,要求使用的內存不能超過1G。
講解:可以建立一棵trie樹(3百萬個字符串,大約為765M,小於1G),在關鍵字域存儲其串的出現次數,然后用小頂堆求前10個字符串。或者利用Hash將1000萬記錄哈希到300萬的范圍內,統計每個記錄的頻度(用trie或hash_map)。然后用維護一個大小為10的小頂堆遍歷這300萬的統計結果。