php sdbmhash,关于php:phpRedis实现的布隆过滤器

因为Redis实现了setbit和getbit操作,人造适宜实现布隆过滤器,redis也有布隆过滤器插件。这里应用php+redis实现布隆过滤器。

首先定义一个hash函数汇合类,这些hash函数不肯定都用到,实际上32位hash值的用3个就能够了,具体的数量能够依据你的位序列总量和你须要存入的量决定,下面曾经给出最佳值。

class BloomFilterHash

{

/**

* 由Justin Sobel编写的按位散列函数

*/

public function JSHash($string, $len = null)

{

$hash = 1315423911;

$len || $len = strlen($string);

for ($i=0; $i

$hash ^= (($hash << 5) + ord($string[$i]) + ($hash >> 2));

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

/**

* 该哈希算法基于AT&T贝尔实验室的Peter J. Weinberger的工作。

* Aho Sethi和Ulman编写的“编译器(原理,技术和工具)”一书倡议应用采纳此特定算法中的散列办法的散列函数。

*/

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

$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性能,但针对32位处理器进行了调整。它是基于UNIX的零碎上的widley应用哈希函数。

*/

public function ELFHash($string, $len = null)

{

$hash = 0;

$len || $len = strlen($string);

for ($i=0; $i

$hash = ($hash << 4) + ord($string[$i]); $x = $hash & 0xF0000000; if ($x != 0) { $hash ^= ($x >> 24);

}

$hash &= ~$x;

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

/**

* 这个哈希函数来自Brian Kernighan和Dennis Ritchie的书“The C Programming Language”。

* 它是一个简略的哈希函数,应用一组奇怪的可能种子,它们都形成了31 .... 31 ... 31等模式,它仿佛与DJB哈希函数十分类似。

*/

public function BKDRHash($string, $len = null)

{

$seed = 131; # 31 131 1313 13131 131313 etc..

$hash = 0;

$len || $len = strlen($string);

for ($i=0; $i

$hash = (int) (($hash * $seed) + ord($string[$i]));

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

/**

* 这是在开源SDBM我的项目中应用的首选算法。

* 哈希函数仿佛对许多不同的数据集具备良好的总体散布。它仿佛实用于数据集中元素的MSB存在高差别的状况。

*/

public function SDBMHash($string, $len = null)

{

$hash = 0;

$len || $len = strlen($string);

for ($i=0; $i

$hash = (int) (ord($string[$i]) + ($hash << 6) + ($hash << 16) - $hash);

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

/**

* 由Daniel J. Bernstein传授制作的算法,首先在usenet新闻组comp.lang.c上向世界展现。

* 它是有史以来公布的最无效的哈希函数之一。

*/

public function DJBHash($string, $len = null)

{

$hash = 5381;

$len || $len = strlen($string);

for ($i=0; $i

$hash = (int) (($hash << 5) + $hash) + ord($string[$i]);

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

/**

* Donald E. Knuth在“计算机编程艺术第3卷”中提出的算法,主题是排序和搜寻第6.4章。

*/

public function DEKHash($string, $len = null)

{

$len || $len = strlen($string);

$hash = $len;

for ($i=0; $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

$hash = (int) ($hash * $prime) % 0xFFFFFFFF;

$hash ^= ord($string[$i]);

}

return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;

}

}

接着就是连贯redis来进行操作

/**

* 应用redis实现的布隆过滤器

*/

abstract class BloomFilterRedis

{

/**

* 须要应用一个办法来定义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; //假如这里你曾经连贯好了

}

/**

* 增加到汇合中

*/

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();

}

/**

* 查问是否存在, 如果已经写入过,必然回true,如果没写入过,有肯定几率会误判为存在

*/

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;

}

}

下面定义的是一个抽象类,如果要应用,能够依据具体的业务来应用。比方上面是一个过滤反复内容的过滤器。

/**

* 反复内容过滤器

* 该布隆过滤器总位数为2^32位, 判断条数为2^30条. hash函数最优为3个.(可能容忍最多的hash函数个数)

* 应用的三个hash函数为

* BKDR, SDBM, JSHash

*

* 留神, 在存储的数据量到2^30条时候, 误判率会急剧减少, 因而须要定时判断过滤器中的位为1的的数量是否超过50%, 超过则须要清空.

*/

class FilteRepeatedComments extends BloomFilterRedis

{

/**

* 示意判断反复内容的过滤器

* @var string

*/

protected $bucket = 'rptc';

protected $hashFunction = array('BKDRHash', 'SDBMHash', 'JSHash');

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值