本篇內(nèi)容主要講解“如何使用php+redis實(shí)現(xiàn)布隆過(guò)濾器”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何使用php+redis實(shí)現(xiàn)布隆過(guò)濾器”吧!
創(chuàng)新互聯(lián)公司專注于布爾津企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),商城系統(tǒng)網(wǎng)站開發(fā)。布爾津網(wǎng)站建設(shè)公司,為布爾津等地區(qū)提供建站服務(wù)。全流程按需定制設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)
首先定義一個(gè)hash函數(shù)集合類,這些hash函數(shù)不一定都用到,實(shí)際上32位hash值的用3個(gè)就可以了,具體的數(shù)量可以根據(jù)你的位序列總量和你需要存入的量決定,上面已經(jīng)給出最佳值。
class BloomFilterHash { /** * 由Justin Sobel編寫的按位散列函數(shù) */ public function JSHash($string, $len = null) { $hash = 1315423911; $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash ^= (($hash << 5) + ord($string[$i]) + ($hash >> 2)); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 該哈希算法基于AT&T貝爾實(shí)驗(yàn)室的Peter J. Weinberger的工作。 * Aho Sethi和Ulman編寫的“編譯器(原理,技術(shù)和工具)”一書建議使用采用此特定算法中的散列方法的散列函數(shù)。 */ public function PJWHash($string, $len = null) { $bitsInUnsignedInt = 4 * 8; //(unsigned int)(sizeof(unsigned int)* 8); $threeQuarters = ($bitsInUnsignedInt * 3) / 4; $oneEighth = $bitsInUnsignedInt / 8; $highBits = 0xFFFFFFFF << (int) ($bitsInUnsignedInt - $oneEighth); $hash = 0; $test = 0; $len || $len = strlen($string); for($i=0; $i<$len; $i++) { $hash = ($hash << (int) ($oneEighth)) + ord($string[$i]); } $test = $hash & $highBits; if ($test != 0) { $hash = (($hash ^ ($test >> (int)($threeQuarters))) & (~$highBits)); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 類似于PJW Hash功能,但針對(duì)32位處理器進(jìn)行了調(diào)整。它是基于UNIX的系統(tǒng)上的widley使用哈希函數(shù)。 */ public function ELFHash($string, $len = null) { $hash = 0; $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash = ($hash << 4) + ord($string[$i]); $x = $hash & 0xF0000000; if ($x != 0) { $hash ^= ($x >> 24); } $hash &= ~$x; } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 這個(gè)哈希函數(shù)來(lái)自Brian Kernighan和Dennis Ritchie的書“The C Programming Language”。 * 它是一個(gè)簡(jiǎn)單的哈希函數(shù),使用一組奇怪的可能種子,它們都構(gòu)成了31 .... 31 ... 31等模式,它似乎與DJB哈希函數(shù)非常相似。 */ public function BKDRHash($string, $len = null) { $seed = 131; # 31 131 1313 13131 131313 etc.. $hash = 0; $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash = (int) (($hash * $seed) + ord($string[$i])); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 這是在開源SDBM項(xiàng)目中使用的首選算法。 * 哈希函數(shù)似乎對(duì)許多不同的數(shù)據(jù)集具有良好的總體分布。它似乎適用于數(shù)據(jù)集中元素的MSB存在高差異的情況。 */ public function SDBMHash($string, $len = null) { $hash = 0; $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash = (int) (ord($string[$i]) + ($hash << 6) + ($hash << 16) - $hash); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 由Daniel J. Bernstein教授制作的算法,首先在usenet新聞組comp.lang.c上向世界展示。 * 它是有史以來(lái)發(fā)布的最有效的哈希函數(shù)之一。 */ public function DJBHash($string, $len = null) { $hash = 5381; $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash = (int) (($hash << 5) + $hash) + ord($string[$i]); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * Donald E. Knuth在“計(jì)算機(jī)編程藝術(shù)第3卷”中提出的算法,主題是排序和搜索第6.4章。 */ public function DEKHash($string, $len = null) { $len || $len = strlen($string); $hash = $len; for ($i=0; $i<$len; $i++) { $hash = (($hash << 5) ^ ($hash >> 27)) ^ ord($string[$i]); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } /** * 參考 http://www.isthe.com/chongo/tech/comp/fnv/ */ public function FNVHash($string, $len = null) { $prime = 16777619; //32位的prime 2^24 + 2^8 + 0x93 = 16777619 $hash = 2166136261; //32位的offset $len || $len = strlen($string); for ($i=0; $i<$len; $i++) { $hash = (int) ($hash * $prime) % 0xFFFFFFFF; $hash ^= ord($string[$i]); } return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF; } }
接著就是連接redis來(lái)進(jìn)行操作
/** * 使用redis實(shí)現(xiàn)的布隆過(guò)濾器 */ abstract class BloomFilterRedis { /** * 需要使用一個(gè)方法來(lái)定義bucket的名字 */ protected $bucket; protected $hashFunction; public function __construct($config, $id) { if (!$this->bucket || !$this->hashFunction) { throw new Exception("需要定義bucket和hashFunction", 1); } $this->Hash = new BloomFilterHash; $this->Redis = new YourRedis; //假設(shè)這里你已經(jīng)連接好了 } /** * 添加到集合中 */ public function add($string) { $pipe = $this->Redis->multi(); foreach ($this->hashFunction as $function) { $hash = $this->Hash->$function($string); $pipe->setBit($this->bucket, $hash, 1); } return $pipe->exec(); } /** * 查詢是否存在, 如果曾經(jīng)寫入過(guò),必定回true,如果沒(méi)寫入過(guò),有一定幾率會(huì)誤判為存在 */ public function exists($string) { $pipe = $this->Redis->multi(); $len = strlen($string); foreach ($this->hashFunction as $function) { $hash = $this->Hash->$function($string, $len); $pipe = $pipe->getBit($this->bucket, $hash); } $res = $pipe->exec(); foreach ($res as $bit) { if ($bit == 0) { return false; } } return true; } }
上面定義的是一個(gè)抽象類,如果要使用,可以根據(jù)具體的業(yè)務(wù)來(lái)使用。比如下面是一個(gè)過(guò)濾重復(fù)內(nèi)容的過(guò)濾器。
/** * 重復(fù)內(nèi)容過(guò)濾器 * 該布隆過(guò)濾器總位數(shù)為2^32位, 判斷條數(shù)為2^30條. hash函數(shù)最優(yōu)為3個(gè).(能夠容忍最多的hash函數(shù)個(gè)數(shù)) * 使用的三個(gè)hash函數(shù)為 * BKDR, SDBM, JSHash * * 注意, 在存儲(chǔ)的數(shù)據(jù)量到2^30條時(shí)候, 誤判率會(huì)急劇增加, 因此需要定時(shí)判斷過(guò)濾器中的位為1的的數(shù)量是否超過(guò)50%, 超過(guò)則需要清空. */ class FilteRepeatedComments extends BloomFilterRedis { /** * 表示判斷重復(fù)內(nèi)容的過(guò)濾器 * @var string */ protected $bucket = 'rptc'; protected $hashFunction = array('BKDRHash', 'SDBMHash', 'JSHash'); }
到此,相信大家對(duì)“如何使用php+redis實(shí)現(xiàn)布隆過(guò)濾器”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
分享名稱:如何使用php+redis實(shí)現(xiàn)布隆過(guò)濾器
分享URL:http://vcdvsql.cn/article30/jhgspo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、網(wǎng)站改版、服務(wù)器托管、用戶體驗(yàn)、面包屑導(dǎo)航、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)