php 大數(shù)據(jù)量及海量數(shù)據(jù)處理算法總結(jié)

下面的方法是我對海量數(shù)據(jù)的處理方法進行了一個一般性的總結(jié)菜职,當(dāng)然這些方法可能并不能完全覆蓋所有的問題铁瞒,但是這樣的一些方法也基本可以處理絕大多數(shù)遇到的問題身冬。下面的一些問題基本直接來源于公司的面試筆試題目桐筏,方法不一定最優(yōu)液荸,如果你有更好的處理方法,歡迎與我討論琉苇。

1.Bloom filter

適用范圍:可以用來實現(xiàn)數(shù)據(jù)字典嘲玫,進行數(shù)據(jù)的判重,或者集合求交集

基本原理及要點:

對于原理來說很簡單并扇,位數(shù)組+k個獨立hash函數(shù)去团。將hash函數(shù)對應(yīng)的值的位數(shù)組置1,查找時如果發(fā)現(xiàn)所有hash函數(shù)對應(yīng)位都是1說明存在穷蛹,很明顯這個過程并不保證查找的結(jié)果是100%正確的土陪。同時也不支持刪除一個已經(jīng)插入的關(guān)鍵字,因為該關(guān)鍵字對應(yīng)的位會牽動到其他的關(guān)鍵字肴熏。所以一個簡單的改進就是 counting Bloom filter鬼雀,用一個counter數(shù)組代替位數(shù)組,就可以支持刪除了蛙吏。

還有一個比較重要的問題源哩,如何根據(jù)輸入元素個數(shù)n鞋吉,確定位數(shù)組m的大小及hash函數(shù)個數(shù)。當(dāng)hash函數(shù)個數(shù)k=(ln2)*(m/n)時錯誤率最小励烦。在錯誤率不大于E的情況下谓着,m至少要等于n*lg(1/E)才能表示任意n個元素的集合。但m還應(yīng)該更大些坛掠,因為還要保證bit數(shù)組里至少一半為 0赊锚,則m 應(yīng)該>=nlg(1/E)*lge 大概就是nlg(1/E)1.44倍(lg表示以2為底的對數(shù))。

舉個例子我們假設(shè)錯誤率為0.01屉栓,則此時m應(yīng)大概是n的13倍改抡。這樣k大概是8個。

注意這里m與n的單位不同系瓢,m是bit為單位阿纤,而n則是以元素個數(shù)為單位(準(zhǔn)確的說是不同元素的個數(shù))。通常單個元素的長度都是有很多bit的夷陋。所以使用bloom filter內(nèi)存上通常都是節(jié)省的欠拾。

擴展:

Bloom filter將集合中的元素映射到位數(shù)組中,用k(k為哈希函數(shù)個數(shù))個映射位是否全1表示元素在不在這個集合中骗绕。Counting bloom filter(CBF)將位數(shù)組中的每一位擴展為一個counter藐窄,從而支持了元素的刪除操作。Spectral Bloom Filter(SBF)將其與集合元素的出現(xiàn)次數(shù)關(guān)聯(lián)酬土。SBF采用counter中的最小值來近似表示元素的出現(xiàn)頻率荆忍。

問題實例:給你A,B兩個文件,各存放50億條URL撤缴,每條URL占用64字節(jié)刹枉,內(nèi)存限制是4G,讓你找出A,B文件共同的URL屈呕。如果是三個乃至n個文件呢微宝?

根據(jù)這個問題我們來計算下內(nèi)存的占用,4G=2^32大概是40億*8大概是340億虎眨,n=50億蟋软,如果按出錯率0.01算需要的大概是650億個 bit。現(xiàn)在可用的是340億嗽桩,相差并不多岳守,這樣可能會使出錯率上升些。另外如果這些urlip是一一對應(yīng)的碌冶,就可以轉(zhuǎn)換成ip湿痢,則大大簡單了。

2.Hashing

適用范圍:快速查找种樱,刪除的基本數(shù)據(jù)結(jié)構(gòu)蒙袍,通常需要總數(shù)據(jù)量可以放入內(nèi)存

基本原理及要點:

hash函數(shù)選擇,針對字符串嫩挤,整數(shù)害幅,排列,具體相應(yīng)的hash方法岂昭。

碰撞處理以现,一種是open hashing,也稱為拉鏈法约啊;另一種就是closed hashing邑遏,也稱開地址法,opened addressing恰矩。 (http://www.my400800.cn)

擴展:

d-left hashing中的d是多個的意思记盒,我們先簡化這個問題,看一看2-left hashing外傅。2-left hashing指的是將一個哈希表分成長度相等的兩半纪吮,分別叫做T1和T2,給T1和T2分別配備一個哈希函數(shù)萎胰,h1和h2碾盟。在存儲一個新的key時,同時用兩個哈希函數(shù)進行計算技竟,得出兩個地址h1[key]和h2[key]冰肴。這時需要檢查T1中的h1[key]位置和T2中的h2[key]位置,哪一個位置已經(jīng)存儲的(有碰撞的)key比較多榔组,然后將新key存儲在負(fù)載少的位置熙尉。如果兩邊一樣多,比如兩個位置都為空或者都存儲了一個key搓扯,就把新key 存儲在左邊的T1子表中骡尽,2-left也由此而來。在查找一個key時擅编,必須進行兩次hash攀细,同時查找兩個位置。

問題實例:

1).海量日志數(shù)據(jù)爱态,提取出某日訪問百度次數(shù)最多的那個IP谭贪。

IP的數(shù)目還是有限的,最多2^32個锦担,所以可以考慮使用hash將ip直接存入內(nèi)存俭识,然后進行統(tǒng)計。

3.bit-map

適用范圍:可進行數(shù)據(jù)的快速查找洞渔,判重套媚,刪除缚态,一般來說數(shù)據(jù)范圍是int的10倍以下

基本原理及要點:使用bit數(shù)組來表示某些元素是否存在,比如8位電話號碼

擴展:bloom filter可以看做是對bit-map的擴展

問題實例:

1)已知某個文件內(nèi)包含一些電話號碼堤瘤,每個號碼為8位數(shù)字玫芦,統(tǒng)計不同號碼的個數(shù)。

8位最多99 999 999本辐,大概需要99m個bit桥帆,大概10幾m字節(jié)的內(nèi)存即可。

2)2.5億個整數(shù)中找出不重復(fù)的整數(shù)的個數(shù)慎皱,內(nèi)存空間不足以容納這2.5億個整數(shù)老虫。

將bit-map擴展一下,用2bit表示一個數(shù)即可茫多,0表示未出現(xiàn)祈匙,1表示出現(xiàn)一次,2表示出現(xiàn)2次及以上天揖【站恚或者我們不用2bit來進行表示,我們用兩個bit-map即可模擬實現(xiàn)這個2bit-map宝剖。

4.堆

適用范圍:海量數(shù)據(jù)前n大洁闰,并且n比較小,堆可以放入內(nèi)存

基本原理及要點:最大堆求前n小万细,最小堆求前n大扑眉。方法,比如求前n小赖钞,我們比較當(dāng)前元素與最大堆里的最大元素腰素,如果它小于最大元素,則應(yīng)該替換那個最大元素雪营。這樣最后得到的n個元素就是最小的n個弓千。適合大數(shù)據(jù)量,求前n小献起,n的大小比較小的情況洋访,這樣可以掃描一遍即可得到所有的前n元素,效率很高谴餐。

擴展:雙堆姻政,一個最大堆與一個最小堆結(jié)合,可以用來維護中位數(shù)岂嗓。

問題實例:

1)100w個數(shù)中找最大的前100個數(shù)汁展。

用一個100個元素大小的最小堆即可。

5.雙層桶劃分 ----其實本質(zhì)上就是【分而治之】的思想,重在“分”的技巧上食绿!

適用范圍:第k大侈咕,中位數(shù),不重復(fù)或重復(fù)的數(shù)字

基本原理及要點:因為元素范圍很大器紧,不能利用直接尋址表耀销,所以通過多次劃分,逐步確定范圍品洛,然后最后在一個可以接受的范圍內(nèi)進行树姨∧ν埃可以通過多次縮小桥状,雙層只是一個例子。

擴展:

問題實例:

1).2.5億個整數(shù)中找出不重復(fù)的整數(shù)的個數(shù)硝清,內(nèi)存空間不足以容納這2.5億個整數(shù)辅斟。

有點像鴿巢原理,整數(shù)個數(shù)為2^32,也就是芦拿,我們可以將這2^32個數(shù)士飒,劃分為2^8個區(qū)域(比如用單個文件代表一個區(qū)域),然后將數(shù)據(jù)分離到不同的區(qū)域蔗崎,然后不同的區(qū)域在利用bitmap就可以直接解決了酵幕。也就是說只要有足夠的磁盤空間,就可以很方便的解決缓苛。

2).5億個int找它們的中位數(shù)芳撒。

這個例子比上面那個更明顯。首先我們將int劃分為2^16個區(qū)域未桥,然后讀取數(shù)據(jù)統(tǒng)計落到各個區(qū)域里的數(shù)的個數(shù)笔刹,之后我們根據(jù)統(tǒng)計結(jié)果就可以判斷中位數(shù)落到那個區(qū)域,同時知道這個區(qū)域中的第幾大數(shù)剛好是中位數(shù)冬耿。然后第二次掃描我們只統(tǒng)計落在這個區(qū)域中的那些數(shù)就可以了舌菜。

實際上,如果不是int是int64亦镶,我們可以經(jīng)過3次這樣的劃分即可降低到可以接受的程度日月。即可以先將int64分成2^24個區(qū)域,然后確定區(qū)域的第幾大數(shù)缤骨,在將該區(qū)域分成2^20個子區(qū)域山孔,然后確定是子區(qū)域的第幾大數(shù),然后子區(qū)域里的數(shù)的個數(shù)只有2^20荷憋,就可以直接利用direct addr table進行統(tǒng)計了台颠。

6.數(shù)據(jù)庫索引

適用范圍:大數(shù)據(jù)量的增刪改查

基本原理及要點:利用數(shù)據(jù)的設(shè)計實現(xiàn)方法,對海量數(shù)據(jù)的增刪改查進行處理。

擴展:

問題實例:

7.倒排索引(Inverted index)

適用范圍:搜索引擎串前,關(guān)鍵字查詢

基本原理及要點:為何叫倒排索引瘫里?一種索引方法,被用來存儲在全文搜索下某個單詞在一個文檔或者一組文檔中的存儲位置的映射荡碾。

以英文為例谨读,下面是要被索引的文本:

T0 = "it is what it is"

T1 = "what is it"

T2 = "it is a banana"

我們就能得到下面的反向文件索引:

"a": {2}

"banana": {2}

"is": {0, 1, 2}

"it": {0, 1, 2}

"what": {0, 1}

檢索的條件"what", "is" 和 "it" 將對應(yīng)集合的交集。

正向索引開發(fā)出來用來存儲每個文檔的單詞的列表坛吁。正向索引的查詢往往滿足每個文檔有序頻繁的全文查詢和每個單詞在校驗文檔中的驗證這樣的查詢劳殖。在正向索引中,文檔占據(jù)了中心的位置拨脉,每個文檔指向了一個它所包含的索引項的序列哆姻。也就是說文檔指向了它包含的那些單詞,而反向索引則是單詞指向了包含它的文檔玫膀,很容易看到這個反向的關(guān)系矛缨。

擴展:

問題實例:文檔檢索系統(tǒng),查詢那些文件包含了某單詞帖旨,比如常見的學(xué)術(shù)論文的關(guān)鍵字搜索箕昭。

8.外排序

適用范圍:大數(shù)據(jù)的排序,去重

基本原理及要點:外排序的歸并方法解阅,置換選擇 敗者樹原理落竹,最優(yōu)歸并樹

擴展:

問題實例:

1).有一個1G大小的一個文件,里面每一行是一個詞货抄,詞的大小不超過16個字節(jié)述召,內(nèi)存限制大小是1M。返回頻數(shù)最高的100個詞碉熄。

這個數(shù)據(jù)具有很明顯的特點桨武,詞的大小為16個字節(jié),但是內(nèi)存只有1m做hash有些不夠锈津,所以可以用來排序呀酸。內(nèi)存可以當(dāng)輸入緩沖區(qū)使用。

9.trie樹

適用范圍:數(shù)據(jù)量大琼梆,重復(fù)多性誉,但是數(shù)據(jù)種類小可以放入內(nèi)存

基本原理及要點:實現(xiàn)方式,節(jié)點孩子的表示方式

擴展:壓縮實現(xiàn)茎杂。

問題實例:

1).有10個文件错览,每個文件1G, 每個文件的每一行都存放的是用戶的query煌往,每個文件的query都可能重復(fù)倾哺。要你按照query的頻度排序 轧邪。

2).1000萬字符串,其中有些是相同的(重復(fù)),需要把重復(fù)的全部去掉羞海,保留沒有重復(fù)的字符串忌愚。請問怎么設(shè)計和實現(xiàn)?

3).尋找熱門查詢:查詢串的重復(fù)度比較高却邓,雖然總數(shù)是1千萬硕糊,但如果除去重復(fù)后,不超過3百萬個腊徙,每個不超過255字節(jié)简十。

10.分布式處理 mapreduce

適用范圍:數(shù)據(jù)量大,但是數(shù)據(jù)種類小可以放入內(nèi)存

基本原理及要點:將數(shù)據(jù)交給不同的機器去處理撬腾,數(shù)據(jù)劃分螟蝙,結(jié)果歸約。

擴展:

問題實例:

1).The canonical example application of MapReduce is a process to count the appearances of

each different word in a set of documents:

void map(String name, String document):

// name: document name

// document: document contents

for each word w in document:

EmitIntermediate(w, 1);

void reduce(String word, Iterator partialCounts):

// key: a word

// values: a list of aggregated partial counts

int result = 0;

for each v in partialCounts:

result += ParseInt(v);

Emit(result);

Here, each document is split in words, and each word is counted initially with a "1" value by

the Map function, using the word as the result key. The framework puts together all the pairs

with the same key and feeds them to the same call to Reduce, thus this function just needs to

sum all of its input values to find the total appearances of that word.

2).海量數(shù)據(jù)分布在100臺電腦中时鸵,想個辦法高效統(tǒng)計出這批數(shù)據(jù)的TOP10胶逢。

3).一共有N個機器厅瞎,每個機器上有N個數(shù)饰潜。每個機器最多存O(N)個數(shù)并對它們操作。如何找到N^2個數(shù)的中數(shù)(median)和簸?

經(jīng)典問題分析

上千萬or億數(shù)據(jù)(有重復(fù))彭雾,統(tǒng)計其中出現(xiàn)次數(shù)最多的前N個數(shù)據(jù),分兩種情況:可一次讀入內(nèi)存,不可一次讀入锁保。

可用思路:trie樹+堆薯酝,數(shù)據(jù)庫索引,劃分子集分別統(tǒng)計爽柒,hash吴菠,分布式計算,近似統(tǒng)計浩村,外排序

所謂的是否能一次讀入內(nèi)存做葵,實際上應(yīng)該指去除重復(fù)后的數(shù)據(jù)量。如果去重后數(shù)據(jù)可以放入內(nèi)存心墅,我們可以為數(shù)據(jù)建立字典酿矢,比如通過 map,hashmap怎燥,trie瘫筐,然后直接進行統(tǒng)計即可。當(dāng)然在更新每條數(shù)據(jù)的出現(xiàn)次數(shù)的時候铐姚,我們可以利用一個堆來維護出現(xiàn)次數(shù)最多的前N個數(shù)據(jù)策肝,當(dāng)然這樣導(dǎo)致維護次數(shù)增加,不如完全統(tǒng)計后在求前N大效率高。

如果數(shù)據(jù)無法放入內(nèi)存之众。一方面我們可以考慮上面的字典方法能否被改進以適應(yīng)這種情形篇梭,可以做的改變就是將字典存放到硬盤上,而不是內(nèi)存酝枢,這可以參考數(shù)據(jù)庫的存儲方法恬偷。

當(dāng)然還有更好的方法,就是可以采用分布式計算帘睦,基本上就是map-reduce過程袍患,首先可以根據(jù)數(shù)據(jù)值或者把數(shù)據(jù)hash(md5)后的值,將數(shù)據(jù)按照范圍劃分到不同的機子竣付,最好可以讓數(shù)據(jù)劃分后可以一次讀入內(nèi)存诡延,這樣不同的機子負(fù)責(zé)處理各種的數(shù)值范圍,實際上就是map古胆。得到結(jié)果后肆良,各個機子只需拿出各自的出現(xiàn)次數(shù)最多的前N個數(shù)據(jù),然后匯總逸绎,選出所有的數(shù)據(jù)中出現(xiàn)次數(shù)最多的前N個數(shù)據(jù)惹恃,這實際上就是reduce過程。

實際上可能想直接將數(shù)據(jù)均分到不同的機子上進行處理棺牧,這樣是無法得到正確的解的巫糙。因為一個數(shù)據(jù)可能被均分到不同的機子上,而另一個則可能完全聚集到一個機子上颊乘,同時還可能存在具有相同數(shù)目的數(shù)據(jù)参淹。比如我們要找出現(xiàn)次數(shù)最多的前100個,我們將1000萬的數(shù)據(jù)分布到10臺機器上乏悄,找到每臺出現(xiàn)次數(shù)最多的前 100個浙值,歸并之后這樣不能保證找到真正的第100個,因為比如出現(xiàn)次數(shù)最多的第100個可能有1萬個檩小,但是它被分到了10臺機子开呐,這樣在每臺上只有1千個,假設(shè)這些機子排名在1000個之前的那些都是單獨分布在一臺機子上的识啦,比如有1001個负蚊,這樣本來具有1萬個的這個就會被淘汰,即使我們讓每臺機子選出出現(xiàn)次數(shù)最多的1000個再歸并颓哮,仍然會出錯家妆,因為可能存在大量個數(shù)為1001個的發(fā)生聚集。因此不能將數(shù)據(jù)隨便均分到不同機子上冕茅,而是要根據(jù)hash 后的值將它們映射到不同的機子上處理伤极,讓不同的機器處理一個數(shù)值范圍蛹找。

而外排序的方法會消耗大量的IO,效率不會很高哨坪。而上面的分布式方法庸疾,也可以用于單機版本,也就是將總的數(shù)據(jù)根據(jù)值的范圍当编,劃分成多個不同的子文件届慈,然后逐個處理。處理完畢之后再對這些單詞的及其出現(xiàn)頻率進行一個歸并忿偷。實際上就可以利用一個外排序的歸并過程金顿。

另外還可以考慮近似計算,也就是我們可以通過結(jié)合自然語言屬性鲤桥,只將那些真正實際中出現(xiàn)最多的那些詞作為一個字典揍拆,使得這個規(guī)模可以放入內(nèi)存茶凳。

原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫂拴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贮喧,更是在濱河造成了極大的恐慌筒狠,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件塞淹,死亡現(xiàn)場離奇詭異窟蓝,居然都是意外死亡罪裹,警方通過查閱死者的電腦和手機饱普,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來状共,“玉大人套耕,你說我怎么就攤上這事∠考蹋” “怎么了冯袍?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碾牌。 經(jīng)常有香客問我康愤,道長,這世上最難降的妖魔是什么舶吗? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任征冷,我火速辦了婚禮,結(jié)果婚禮上誓琼,老公的妹妹穿的比我還像新娘检激。我一直安慰自己肴捉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布叔收。 她就那樣靜靜地躺著齿穗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饺律。 梳的紋絲不亂的頭發(fā)上窃页,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音复濒,去河邊找鬼腮出。 笑死,一個胖子當(dāng)著我的面吹牛芝薇,可吹牛的內(nèi)容都是我干的胚嘲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼洛二,長吁一口氣:“原來是場噩夢啊……” “哼馋劈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晾嘶,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤妓雾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后垒迂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體械姻,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年机断,在試婚紗的時候發(fā)現(xiàn)自己被綠了楷拳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吏奸,死狀恐怖欢揖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奋蔚,我是刑警寧澤她混,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站泊碑,受9級特大地震影響坤按,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜馒过,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一臭脓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沉桌,春花似錦谢鹊、人聲如沸算吩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偎巢。三九已至,卻和暖如春兼耀,著一層夾襖步出監(jiān)牢的瞬間压昼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工瘤运, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窍霞,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓拯坟,卻偏偏與公主長得像但金,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子郁季,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容