常見大數據和空間面試題

過濾100億黑名單

題目

假設有100億個URL的黑名單,每一個URL最多佔用64B,設計一個過濾系統,判斷某條URL是否在黑名單裏。數據庫

要求

不高於萬分之一的判斷失誤率;額外內存不超過30GB數組

答案

100億個64B的URL須要640GB的內存,顯然直接存哈希表不合理。考慮布隆過濾器,假設有一個長度爲m的bit類型數組,如圖所示:緩存

clipboard.png

輸入階段:分佈式

有k個哈希函數,函數的輸出域S大於或等於m,假設哈希函數彼此獨立,對於同一個輸入(以字符串表示的URL),通過k個哈希函數的計算結果也是相互獨立。對計算的每個結果Mod m,將bit array上對應的位置置1,以下:memcached

一個輸入對象會將bitmap某些位置塗黑,處理完全部輸入對象,會將bitmap至關多位置塗黑,至此,布隆過濾器生成完畢,表明以前全部輸入對象的集合。函數

clipboard.png

20億個數中出現最多的數

問題

包含20億個全是32位整數的大文件,在其中找出出現次數最多的數。spa

要求

內存限制:2GB設計

答案

將20億個數用hash函數分紅16個文件。而後統計每一個小文件中,哪一個數字出現次數最多。最後再比較每一個小文件的次數最多的數。(本題分紅16個也是根據題目來的。考慮最極端狀況。20億個數都不一樣)32位的整數要佔4b,key佔4b,value佔4b。共8b。內存只有2G。因此大概每一個小文件存2億條。就須要10個小文件。可是hash函數必須2的n次方。因此2的4次方。16個對象

40億個數找沒出現的數

問題

有一個包含40億個無符號整數的文件,最多使用1GB內存,找到全部沒出現的數blog

分析

最差狀況,40億個數都不一樣,哈希表保存出現過的數,須要內存4B*40億,大約16GB內存。

答案

使用bitmap,申請一個長度爲4294967295bit類型的bitArray,每一個位置只表示0或1,該數組佔用空間約500MB。遍歷這20億個數,例如遇到7000,就將bitArray[7000]置1。遍歷完成後,再依次遍歷bitArray,哪一個位置沒有置1,哪一個數就不在40億個數中。

40億個數找第一個沒出現的數 。內存只有10M

答案

具體的,第一次遍歷,申請長度64的整形數組countArr[0...63],統計每一個區間計數增長。例如,當前數是34225522090,34225522090/67108864=51,countArr[51]++。遍歷完以後,一定有一個countArr[i]小於67108864,表示i區間內至少有一個數沒出現過。此時countArr[]使用的內存是64*4B。

假設在37區間有一個數沒出現,申請一個長度爲67108864的bitmap,內存大約8MB,記爲bitArr[0~67108863]。再一次遍歷40億個數,只關心37區間的數,記爲num。將bitAry[num-6710886437]的值置位1。遍歷完以後,bitArr必然有沒有置1的位置,記爲i,則6710886437+i就是沒出現過的數。

找出100億個重複URL以及搜索詞彙topK問題

問題

有一個包含100億URL的大文件,每一個URL佔64B,找出重複URL;補充,找出top100搜索詞彙

常規答案

  1. 大文件經過哈希函數分配到不一樣機器
  2. 哈希函數將大文件拆分紅小文件。

對於每個小文件,利用哈希表遍歷,找出重複的URL,或者分給機器或拆分文件完以後,進行排序,看是否有重複的URL。

補充問題的思路也是經過哈希函數分流,對於每一個小文件,簡歷詞頻哈希表,建一個大小爲100的小根堆,選出每一個小文件的top100.每一個小文件的top100進行外排序或者接着使用小根堆,就能獲得100億數據的top100.

出現兩次的數以及中位數問題

問題

有40億個無符號32位整數,最多可使用1GB內存,找出全部出現了兩次的數;補充問題,最多使用10MB內存,找到40億個數的中位數

答案

第一個問題能夠用bitmap作,申請長度爲2?232bit的bitArr,2個bit表示一個數出現的詞頻。遍歷40億個數,假設出現num,將bitArr[2num]和bitArr[2num+1]設置爲01,第二次出現,設置爲10,第三次,設置爲11。之後再遇到11的,就不作處理。遍歷完成後,再遍歷一次,若發現bitArr[2num]和bitArr[2num+1]是10,則num是出現了兩次的數。

第二個問題,分區間討論。長度爲2MB的unsigned int數組佔用8MB,將區間數目定位232/2M,取整爲2148個區間,第0區間0~2M-1,第i區間2Mi~2M(i+1)-1

申請一個長度爲2148的unsigned int整數數組arr[0..2147],arr[i]表示i區間有多少個數,arr佔用內存小於10MB。遍歷40億個數,當前數num爲num,落在區間(num/2M),對應arr[num/2M]++。累加統計每一個區間的累計數目,就能找到40億個數的中位數。例如0~K-1區間數目個數爲19.998億,加上第K個區間就超過了20億,說要中位數必定在K區間中,而且必定是第K區間的第0.002億個數。

接着申請長度2M的unsigned int數組countArr[0..2M-1],佔用8MB。遍歷40億個數,只關心第K區間的數numi,countArr[numi-K*2M]++。統計完以後在第K區間找地0.002億個數字便可。

一致性哈希

分佈式數據庫集羣緩存,例如memcached,將數據的id經過哈希函數轉換爲key,假設有N個機器,計算key%N,獲得及其所屬編號,增刪改查都在這臺機器上。一致性哈希能在機器擴容(N發生變化),使得不用從新計算一遍key%N

三臺機器處於哈希環,id經過哈希映射爲key,在哈希環中順時針找距離最近的機器。

機器較少的時候可能會出現負載不均衡,如圖所示:

答案

引入虛擬節點,增長結點數

相關文章
相關標籤/搜索