海量數據解決思路之Hash算法


海量數據解決思路之Hash算法

 

一、概述
本文將粗略講述一下Hash算法的概念特性,里邊會結合 分布式系統負載均衡 實例對Hash的一致性做深入探討。另外,探討一下Hash算法在海量數據處理方案中的通用性。最后,從源代碼出發,具體分析一下Hash算法在MapReduce框架的中的應用。

二、Hash算法
Hash可以通過散列函數將任意長度的輸入變成固定長度的輸出,也可以將不同的輸入映射成為相同的相同的輸出,而且這些輸出范圍也是可控制的,所以起到了很好的壓縮映射和等價映射功能。這些特 性被應用到了信息安全領域中加密算法,其中 等價映射這一特性在海量數據解決方案中起到相當大的作用,特別是在整個MapReduce框架中,下面章節會對這二方面詳細說。話說,Hash為什么會有這種 壓縮映射和等價映射功能,主要是因為Hash函數在實現上都使用到了取模。下面看看幾種常用的Hash函數:
・直接取余法:f(x):= x mod maxM ; maxM一般是不太接近 2^t 的一個質數。
・乘法取整法:f(x):=trunc((x/maxX)*maxlongit) mod maxM,主要用於實數。
・平方取中法:f(x):=(x*x div 1000 ) mod 1000000); 平方后取中間的,每位包含信息比較多。
三、Hash算法在海量數據處理方 案中的應用

單機處理海量數據的大體主流思想是和MapReduce框架一樣,都是采取分而治之的方法,將海量數據切分為若干小份來進行處理,並且在處理的過程中要兼顧內存的使用情況和處理並發量情況。而更加仔細的處理流程大體上分為幾步(對大多數情況都使用,其中少部分情況要根據你自己的實際情況和其他解決方法做比較采用最符合實際的方法):

 

  • 第一步:分而治之。

采用Hash取模進行等價映 射。采用這種方法可以將巨大的文件進行等價分割(注意:符合一定規律的數據要被分割到同一個小文件)變成若干個小文件再進行處理。這個方法針對數據量巨大,內存受到限制時十分有效。

 

  • 第二步:利用hashMap在內存中進行統計。

我們通過Hash映射將大文件分割為小文件后,就可以采用HashMap這樣的存儲結構來對小文件中的關注項進行頻率統計。具體的做法是將要進行統計的Item作為HashMap的key,此Item出現的次數作為value。

 

  • 第三步:在上一步進行統計完畢之后根據場景需求往往需要對存儲在HashMap中的數據根據出現的次數來進行排序。其中排序我們可以采用堆排序、快速排序、歸並排序等方法。

現在我們來看看具體的例子:
【例子1】 海量日志數據,提取出某日訪問百度次數最多的那個IP
思路:當看到這樣的業務場景,我們腦子里應該立馬會想到這些海量網關日志數據量有多大?這些IP有多少中組合情況,最大情況下占多少存儲空間?解決這樣的問題前我們最重要的先要知道數據的規模,這樣才能從大體上制定解決方案。所以現在假設這些這些網關日志量有3T。下面大體按照我們上面的步驟來對解決此場景進行分析:

(1)首先,從這些海量數據中過濾出指定一天訪問百度的用戶IP,並逐個寫到一個大文件中。
(2)采用“分而治之”的思想用Hash映射將大文件進行分割降低數據規模。按照IP地址的Hash(IP)%1024值,把海量IP日志分別存儲到1024個小文件中,其中Hash函數得出值為分割后小文件的編號。
( 3)逐個讀小文件,對於每一個小文件構建一個IP為key,出現次數為value的HashMap。對於怎么利用HashMap記錄IP出現的次數這個比較簡單,因為我們可以通過程序讀小文件將IP放到HashMap中key的之后可以先判斷此IP是否已經存在如果不存在直接放進去,其出現次數記錄為1,如果此IP已經存儲則過得其對應的value值也就是出現的次數然后加1就ok。最后,按照IP出現的次數采用排序算法對HashMap中的數據進行排序, 同時記錄當前出現次數最多的那個IP地址;
(4)走到這步,我們可以得到1024個小文件中出現次數最多的IP了,再采用常規的排序算法找出總體上出現次數最多的IP就ok了。
這個我們需要特別地明確知道一下幾點內容:
第一:我們通過Hash函數: Hash(IP)%1024將大文件映射分割為了1024個小文件,那么這1024個小文件的大小是否均勻?另外,我們采用HashMap來進行IP頻率的統計,內存消耗是否合適?

 

  • 首先是第一個問題,被分割的小文件的大小的均勻程度是取決於我們使用怎么樣的Hash函數 ,對本場景而言就是: Hash(IP)%1024。設計良好的Hash函數可以減少沖突,使數據均勻的分割到1024個小文件中。但是 盡管數據映射到了另外一些不同的位置,但數據還是原來的數據,只是代替和表示這些原始數據的形式發生了變化而已。
  • 另外,看看第二個問題:用HashMap統計IP出現頻率的內存使用情況。

要想知道HashMap在統計IP出現的頻率,那么我們必須對IP組合的情況有所了解。32Bit的IP最多可以有2^32種的組合方式,也就是說去所有IP最多占4G存儲空間。在此場景中,我們已經根據IP的hash值將大文件分割出了1024個小文件,也就是說這4G的IP已經被分散到了1024個文件中。那么在Hash函數設計合理最perfect的情況下針對每個小文件的HashMap占的內存大小最多為4G/1024+存儲IP對應的次數所占的空間,所以內存絕對夠用。
第二:Hash取模是一種等價映射,換句話說通過映射分割之后相同的元素只會分到同一個小文件中去的。就本場景而言,相同的IP通過Hash函數后只會被分割到這1024個小文件中的其中一個文件。
【例子2】 給定a、b兩個文件,各存放50億個url,每個url各占64字節,內存限制是4G,讓你找出a、b文件共同的url?
思路:還是老一套,先Hash映射降低數據規模,然后統計排序。

具體做法:
(1)分析現有數據的規模。
按照每個url64字節來算,每個文件有50億個url,那么每個文件大小為5G*64=320G。320G遠遠超出內存限定的4G,所以不能將其全部加載到內存中來進行處理,需要采用分而治之的方法進行處理。

(2)Hash映射分割文件。逐行讀取文件a,采用hash函數:Hash(url)%1000將url分割到1000個小文件中,文件即為f1_1,f1_2,f1_3,...,f1_1000。那么理想情況下每個小文件的大小大約為300m左右。再以相同的方法對大文件b進行相同的操作再得到1000個小文件,記為: f2_1,f2_2,f2_3,...,f2_1000。
經過一番折騰后我們將大文件進行了分割並且將相同url都分割到了這2組小文件中下標相同的兩個文件中,其實我們可以將這2組文件看成一個整體: f1_1& f2_1, f1_2& ,f2_2, f1_3& f2_3,..., f1_1000& f2_1000。那么我們就可以將問題轉化成為求這1000對小文件中相同的url就可以了。接下來,求每對小文件中的相同url,首先將每對對小文件中較小的那個的url放到HashSet結構中,然后遍歷對應這對小文件中的另一個文件,看其是否存才剛剛構建的HashSet中,如果存在說明是一樣的url,將這url直接存到結果文件就ok了。
【例子3】有10個文件,每個文件1G,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重復。要求你按照query的頻度排序。
【例子4】 有一個1G大小的一個文件,里面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。
像例子3和例子4這些場景都可以用我們的一貫老招數解決:先Hash映射降低數據規模,然后統計加載到內存,最后排序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM