PHP中實(shí)現(xiàn)Bloom Filter算法
來(lái)源:易賢網(wǎng) 閱讀:729 次 日期:2015-04-03 10:32:02
溫馨提示:易賢網(wǎng)小編為您整理了“PHP中實(shí)現(xiàn)Bloom Filter算法”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了PHP中實(shí)現(xiàn)Bloom Filter算法,本文直接給出實(shí)現(xiàn)代碼,代碼中給出詳細(xì)注釋,Bloom Filter算法介紹等內(nèi)容,需要的朋友可以參考下

<?php

/*Bloom Filter算法來(lái)去重過(guò)濾。

介紹下Bloom Filter的基本處理思路:申請(qǐng)一批空間用于保存0 1信息,再根據(jù)一批哈希函數(shù)確定元素對(duì)應(yīng)的位置,如果每個(gè)哈希函數(shù)對(duì)應(yīng)位置的值為全部1,說(shuō)明此元素存在。相反,如果為0,則要把對(duì)應(yīng)位置的值設(shè)置為1。由于不同的元素可能會(huì)有相同的哈希值,即同一個(gè)位置有可能保存了多個(gè)元素的信息,從而導(dǎo)致存在一定的誤判率。

如果申請(qǐng)空間太小,隨著元素的增多,1會(huì)越來(lái)越多,各個(gè)元素沖突的機(jī)會(huì)越來(lái)越來(lái)大,導(dǎo)致誤判率會(huì)越來(lái)越大。另外哈希函數(shù)的選擇及個(gè)數(shù)上也要平衡好,多個(gè)哈希函數(shù)雖然可以提供判斷的準(zhǔn)確性,但是會(huì)降低程序的處理速度,而哈希函數(shù)的增加又要求有更多的空間來(lái)存儲(chǔ)位置信息。

Bloom-Filter的應(yīng)用。

Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在。例如郵件服務(wù)器中的垃圾郵件過(guò)濾器。在搜索引擎領(lǐng)域,Bloom-Filter最常用于網(wǎng)絡(luò)蜘蛛(Spider)的URL過(guò)濾,網(wǎng)絡(luò)蜘蛛通常有一個(gè) URL列表,保存著將要下載和已經(jīng)下載的網(wǎng)頁(yè)的URL,網(wǎng)絡(luò)蜘蛛下載了一個(gè)網(wǎng)頁(yè),從網(wǎng)頁(yè)中提取到新的URL后,需要判斷該URL是否已經(jīng)存在于列表中。此時(shí),Bloom-Filter算法是最好的選擇。

比如說(shuō),一個(gè)象 Yahoo,Hotmail 和 Gmai 那樣的公眾電子郵件(email)提供商,總是需要過(guò)濾來(lái)自發(fā)送垃圾郵件的人(spamer)的垃圾郵件。一個(gè)辦法就是記錄下那些發(fā)垃圾郵件的 email 地址。由于那些發(fā)送者不停地在注冊(cè)新的地址,全世界少說(shuō)也有幾十億個(gè)發(fā)垃圾郵件的地址,將他們都存起來(lái)則需要大量的網(wǎng)絡(luò)服務(wù)器。

布隆過(guò)濾器是由巴頓.布隆于一九七零年提出的。它實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù)。我們通過(guò)上面的例子來(lái)說(shuō)明起工作原理。

假定我們存儲(chǔ)一億個(gè)電子郵件地址,我們先建立一個(gè)十六億二進(jìn)制(比特),即兩億字節(jié)的向量,然后將這十六億個(gè)二進(jìn)制位全部設(shè)置為零。對(duì)于每一個(gè)電子郵件地址 X,我們用八個(gè)不同的隨機(jī)數(shù)產(chǎn)生器(F1,F2, ...,F8) 產(chǎn)生八個(gè)信息指紋(f1, f2, ..., f8)。再用一個(gè)隨機(jī)數(shù)產(chǎn)生器 G 把這八個(gè)信息指紋映射到 1 到十六億中的八個(gè)自然數(shù) g1, g2, ...,g8?,F(xiàn)在我們把這八個(gè)位置的二進(jìn)制位全部設(shè)置為一。當(dāng)我們對(duì)這一億個(gè) email 地址都進(jìn)行這樣的處理后。一個(gè)針對(duì)這些 email 地址的布隆過(guò)濾器就建成了。(見(jiàn)下圖) 現(xiàn)在,讓我們看看如何用布隆過(guò)濾器來(lái)檢測(cè)一個(gè)可疑的電子郵件地址 Y 是否在黑名單中。我們用相同的八個(gè)隨機(jī)數(shù)產(chǎn)生器(F1, F2, ..., F8)對(duì)這個(gè)地址產(chǎn)生八個(gè)信息指紋 s1,s2,...,s8,然后將這八個(gè)指紋對(duì)應(yīng)到布隆過(guò)濾器的八個(gè)二進(jìn)制位,分別是 t1,t2,...,t8。如果 Y 在黑名單中,顯然,t1,t2,..,t8 對(duì)應(yīng)的八個(gè)二進(jìn)制一定是一。這樣在遇到任何在黑名單中的電子郵件地址,我們都能準(zhǔn)確地發(fā)現(xiàn)。

布隆過(guò)濾器決不會(huì)漏掉任何一個(gè)在黑名單中的可疑地址。但是,它有一條不足之處。也就是它有極小的可能將一個(gè)不在黑名單中的電子郵件地址判定為在黑名單中,因?yàn)橛锌赡苣硞€(gè)好的郵件地址正巧對(duì)應(yīng)八個(gè)都被設(shè)置成一的二進(jìn)制位。好在這種可能性很小。我們把它稱(chēng)為誤識(shí)概率。在上面的例子中,誤識(shí)概率在萬(wàn)分之一以下。

布隆過(guò)濾器的好處在于快速,省空間。但是有一定的誤識(shí)別率。常見(jiàn)的補(bǔ)救辦法是在建立一個(gè)小的白名單,存儲(chǔ)那些可能別誤判的郵件地址。

*/

// 使用php程序來(lái)描述上面的算法

$set = array(1,2,3,4,5,6);

// 判斷5是否在$set 中

$bloomFiter = array(0,0,0,0,0,0,0,0,0,0);

// 通過(guò)某種算法改變$bloomFiter 中位數(shù)組表示集合,這里我們使用簡(jiǎn)單的算法,把集合中對(duì)應(yīng)的value 對(duì)應(yīng)到bloom中的位置變成1

// 算法如下

foreach($set as $key){

$bloomFiter[$key] = 1 ;

}

var_dump($bloomFiter) ;

//此時(shí) $bloomFiter = array(1,1,1,1,1,1);

//判斷是否在集合中

if($bloomFiter[9] ==1){

echo '在set 中';

}else{

echo '不在set 中' ;

}

// 上面只是一個(gè)簡(jiǎn)單的例子,實(shí)際上哈希算法需要好幾個(gè),但另一方面,如果哈希函數(shù)的個(gè)數(shù)少,那么位數(shù)組中的0就多

class bloom_filter {

function __construct($hash_func_num=1, $space_group_num=1) {

$max_length = pow(2, 25);

$binary = pack('C', 0);

//1字節(jié)占用8位

$this->one_num = 8;

//默認(rèn)32m*1

$this->space_group_num = $space_group_num;

$this->hash_space_assoc = array();

//分配空間

for($i=0; $i<$this->space_group_num; $i++){

$this->hash_space_assoc[$i] = str_repeat($binary, $max_length);

}

$this->pow_array = array(

0 => 1,

1 => 2,

2 => 4,

3 => 8,

4 => 16,

5 => 32,

6 => 64,

7 => 128,

);

$this->chr_array = array();

$this->ord_array = array();

for($i=0; $i<256; $i++){

$chr = chr($i);

$this->chr_array[$i] = $chr;

$this->ord_array[$chr] = $i;

}

$this->hash_func_pos = array(

0 => array(0, 7, 1),

1 => array(7, 7, 1),

2 => array(14, 7, 1),

3 => array(21, 7, 1),

4 => array(28, 7, 1),

5 => array(33, 7, 1),

6 => array(17, 7, 1),

);

$this->write_num = 0;

$this->ext_num = 0;

if(!$hash_func_num){

$this->hash_func_num = count($this->hash_func_pos);

}

else{

$this->hash_func_num = $hash_func_num;

}

}

function add($key) {

$hash_bit_set_num = 0;

// 離散key

$hash_basic = sha1($key);

// 截取前4位,然后十六進(jìn)制轉(zhuǎn)換為十進(jìn)制

$hash_space = hexdec(substr($hash_basic, 0, 4));

// 取模

$hash_space = $hash_space % $this->space_group_num;

for($hash_i=0; $hash_i<$this->hash_func_num; $hash_i++){

$hash = hexdec(substr($hash_basic, $this->hash_func_pos[$hash_i][0], $this->hash_func_pos[$hash_i][1]));

$bit_pos = $hash >> 3;

$max = $this->ord_array[$this->hash_space_assoc[$hash_space][$bit_pos]];

$num = $hash - $bit_pos * $this->one_num;

$bit_pos_value = ($max >> $num) & 0x01;

if(!$bit_pos_value){

$max = $max | $this->pow_array[$num];

$this->hash_space_assoc[$hash_space][$bit_pos] = $this->chr_array[$max];

$this->write_num++;

}

else{

$hash_bit_set_num++;

}

}

if($hash_bit_set_num == $this->hash_func_num){

$this->ext_num++;

return true;

}

return false;

}

function get_stat() {

return array(

'ext_num' => $this->ext_num,

'write_num' => $this->write_num,

);

}

}

//test

//取6個(gè)哈希值,目前是最多7個(gè)

$hash_func_num = 6;

//分配1個(gè)存儲(chǔ)空間,每個(gè)空間為32M,理論上是空間越大誤判率越低,注意php.ini中可使用的內(nèi)存限制

$space_group_num = 1;

$bf = new bloom_filter($hash_func_num, $space_group_num);

$list = array(

'http://test/1',

'http://test/2',

'http://test/3',

'http://test/4',

'http://test/5',

'http://test/6',

'http://test/1',

'http://test/2',

);

foreach($list as $k => $v){

if($bf->add($v)){

echo $v, "n";

}

}

更多信息請(qǐng)查看IT技術(shù)專(zhuān)欄

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:PHP中實(shí)現(xiàn)Bloom Filter算法
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢(xún)回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門(mén)公布的正式信息和咨詢(xún)?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽(tīng)報(bào)名

  • 報(bào)班類(lèi)型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢(xún) | 簡(jiǎn)要咨詢(xún)須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專(zhuān)用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢(xún)關(guān)注公眾號(hào):hfpxwx
咨詢(xún)QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專(zhuān)用圖標(biāo)