快速URL排重的方法 一

2021-08-22 09:40:16 字數 1267 閱讀 6758

我這裡介紹乙個極適合大量url快速排重的方法,這個演算法被稱為bloom filter,基本上,它也只適合這樣的場合。

這裡的大量是指有5000萬至1億的url,更大的資料量可能也不合適了。

所以,把目標鎖定在單機排重,一開始,試驗了perl中的hash,非常簡單的**

db_file;

my%db

;#tie%db,'db_file',"createdb.dat",ordie"can'tinitializedb::$! ";

while

(<>)=

1;#addcodehere

}#untie%db;

從標準輸入或檔案中每行乙個url讀入,插入到perl內建的hash表中,這就成了,需要輸出結果則預先判斷一下插入的key是否存在。

這個方法速度很快,可惜的是,它占用記憶體太大,假設1個url平均50位元組,5000萬個url需要2.5g記憶體。

於是又想到乙個方法,把部分資料放入硬碟空間,perl中也提供乙個現成的模組db_file,把上面**中的注釋去掉,就可使用db_file了,用法與hash一樣,只是內部用資料庫實現的。

測試了一下,速度明顯下降了乙個檔次,僅40萬的資料就要1分鐘,關鍵還在於隨著資料量的增加,速度下降加快,兩者不呈線性關係。

資料量大的時候,有可能用mysql的效能會比db_file好,但是總體上應該是一丘之貉,我已經不抱期望了。

也許db_file可以優化一下,使用更多的記憶體和少量的硬碟空間,不過這個方案還是太複雜,留給專家解決吧,一般來說,我認為簡單的方法才有可能做到高效。

下面我們的重點物件隆重登場:bloom filter。簡單的說是這樣一種方法:在記憶體中開闢一塊區域,對其中所有位置0,然後對資料做10種不同的hash,每個hash值對記憶體bit數求模,求模得到的數在記憶體對應的位上置1。置位之前會先判斷是否已經置位,每次插入乙個url,只有當全部10個位都已經置1了才認為是重複的。

如果對上面這段話不太理解,可以換個簡單的比喻:有10個桶,乙個桶只能容納1個球,每次往這些桶中扔兩個球,如果兩個桶都已經有球,才認為是重複,問問為了不重複總共能扔多少次球?

10次,是這個答案吧?每次扔1個球的話,也是10次。表面上看一次扔幾個球沒有區別,事實上一次兩個球的情況下,重複概率比一次乙個球要低。bloom filter演算法正式借助這一點,僅僅用少量的空間就可以進行大量url的排重,並且使誤判率極低。

有人宣稱為每個url分配兩個位元組就可以達到0衝突,我比較保守,為每個url分配了4個位元組,對於5000萬的數量級,它只占用了100多m的空間,並且排重速度超快,一遍下來不到兩分鐘,極大得滿足了我的慾望。

快速URL排重的方法 一

我這裡介紹乙個極適合大量url快速排重的方法 這個演算法被稱為bloom filter,基本上,它也只適合這樣的場合。這裡的大量是指有5000萬至1億的url,更大的資料量可能也不合適了。所以,把目標鎖定在單機排重,一開始,試驗了perl中的hash,非常簡單的 usedb file my db t...

快速URL排重的方法 二

接上篇,起初我為了輸入輸出方便,是用perl去實現的,後來發現perl中求模速度太慢,就改用c了 常量定義 space指你要分配多大的記憶體空間,我這裡是為5000萬資料的每一條分配4位元組 const intspace 50000000 4 const intmaxnum space 8 defi...

linux排重的方法

想必各位用linux的人都會碰到排重的問題,像檢視乙個日誌檔案,碰到很多重覆記錄,看起來很痛苦。還有像grep一下關鍵字,想找出現關鍵字的檔案,但是出現了一堆重複的檔名,也是一件鬱悶的事情。下面給大家介紹兩種linux排重的方法,一種是使用uniq命令,一種使用gawk。uniq排重 uniq的作用...