時隔一年後的面經總結

這是一條時隔一年後的面試涼經。當時的目標廠家是字節跳動,目標崗位大數據工程師。在此記錄我印象最深刻的一個問題。

由於在大三期間有過實習經歷,寫過爬蟲,並且將這一點寫在了我的求職簡歷中。所以面試官就我在爬蟲系統中是如何處理URL的重複問題的。

URL去重問題:爬蟲在抓取網頁時會抓取到數億條的URL,而這在互聯網種屬九牛一毛。並且網頁中的URL是相互鏈接的,如果抓取到相同的URL,會行程閉環,主要也是爲了節省資源。所以在抓取URL的時候將抓取到的URL放入一個隊列中,對後抓取的URL進行判斷,如果已經存在於隊列中那麼就不進行重複抓取。

我當時的解決辦法是使用HashSet進行去重,因爲HashSet是一個元素不允許重複的集合,這也是最容易想到的辦法,這也是我唯一用過的辦法,由於我的爬蟲系統只爬取特定的網站,所以HashSet足以解決我的業務場景。所以面對面試官的問題我只有一種答案,並且其他的答案也沒跳出set這個範圍。

其實URL的去重方法有很多種,而我能想到的只有第一種。

1、將URL放到Set或HashSet中去重(一億條佔用10G內存)。

2、將URL保存到數據庫進行去重,創建字段的UNIQUE屬性或者創建一個唯一的索引,在插入數據之前檢查待插入的數據是否存在。

3、使用Map或是一個定長數組記錄某一個URL是否被訪問過。

4、使用Bitmap或Bloomfilter方法去重(URL經過hash後映射到bit的每一個位上,一億URL佔用約12M,問題是存在衝突)。

1、2、3解決策略存在的問題

關於Set和Map都是基於內存的(一億條URL約佔用10G內存),隨着URL的不斷抓取一定會發生內存溢出。對於數據庫UNIQUE屬性,將相同的URL插入數據庫數據庫會報錯,如果多次報錯後數據庫會崩潰。如果每次抓取到URL都去數據庫查詢這樣太影響效率。

使用Bitmap方法去重:原理是把URL經過hash後映射到bit的每一個位上,一億URL佔用約12M,主要缺點是去重沒那麼精準,存在衝突。

BloomFilter(布隆過濾器)去重:Bloom Filter是由Bloom在1970年提出的一種多哈希函數映射的快速查找算法。通常應用在一些需要快速判斷某個元素是否屬於集合,但是並不嚴格要求100%正確的場合。

Bloom Filter算法如下: 

(1)創建一個m位BitSet,先將所有位初始化爲0,然後選擇k個不同的哈希函數。第i個哈希函數對字符串str哈希的結果記爲h(i,str),且h(i,str)的範圍是0到m-1 。

(2)將字符串str“記錄”到BitSet中:對於字符串str,分別計算h(1,str),h(2,str)…… h(k,str)。然後將BitSet的第h(1,str)、h(2,str)…… h(k,str)位設爲1。

(3)然後檢查字符串str是否被BitSet記錄過的過程:對於字符串str,分別計算h(1,str),h(2,str)…… h(k,str)。然後檢查BitSet的第h(1,str)、h(2,str)…… h(k,str)位是否爲1,若其中任何一位不爲1則可以判定str一定沒有被記錄過。若全部位都是1,則“認爲”字符串str存在。若一個字符串對應的Bit不全爲1,則可以肯定該字符串一定沒有被Bloom Filter記錄過。(這是顯然的,因爲字符串被記錄過,其對應的二進制位肯定全部被設爲1了)但是若一個字符串對應的Bit全爲1,實際上是不能100%的肯定該字符串被Bloom Filter記錄過的。(因爲有可能該字符串的所有位都剛好是被其他字符串所對應)這種將該字符串劃分錯的情況,稱爲false positive 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章