1.BloomFilter算法
有关BloomFilter的算法介绍和错误率分析参见wiki:
http://en.wikipedia.org/wiki/Bloom_filter
中文版的有一个:
http://blog.csdn.net/jiaomeng/article/details/1495500
2.Bitset介绍
PHP版BloomFilter引入了第三方位操作库bitset,所以使用前需安装bitset环境,下载地址是:
http://pecl.php.net/package/Bitset
BF库主要用到Bitset的4个方法:
- bitset_empty(int bits) - 分配位数组空间,并把每一位初始化为0,位数组长度为bitcount,其实就3行代码:
- len = (bits+CHAR_BIT-1)/CHAR_BIT;
- bitset_data = emalloc( len+1 );
- memset( bitset_data, 0, len+1 );
- bitset_to_string(unsigned char *bitset_data) - 将位数组转换为字符串表示,代码就5行(- -!)
- len *= CHAR_BIT; output_str = emalloc( len+1 ); output_str[ len ] = '\0';
- for(count = 0; count < len; count++ )
- output_str[count ] = ( (bitset_data[ count/CHAR_BIT ] >> (count % CHAR_BIT)) & 1 ) ? '1' : '0';
- bitset_incl(unsigned char *bitset_data, int bit) - 位数组位置bit(之前BF的hash后命中的位置)上的值置为1,实际操作就1行,不过位数组长度做成了动态的,所以还涉及erealloc之类的操作
- bitset_data[ bit/CHAR_BIT ] |= 1 << (bit % CHAR_BIT);
- bitset_in(unsigned char *bitset_data, int bit) - 判断某个位置bit上的值是否为1,位操作语句比较精炼
- if( bitset_data[ bit/CHAR_BIT ] & (1 << (bit % CHAR_BIT) ) )
- RETURN_TRUE;
3.Linux下编译Bitset
下载bitset包,解压,进入目录安装,编译步骤如下
- phpize (该命令是用来准备 PHP 扩展库的编译环境的)
- ./configure
- make
- make install
- 在php.ini添加extension = [编译出来的bitsit.so的位置],重启WebServer即可
Windows下用一些工具根据config.w32编译,步骤比较复杂,俺也没搞懂,回头研究
4.BloomFilter源码分析
-
- class BloomFilter
- {
- public $field; // 位数组
-
- public $len; // 位数组长度
-
- // BF自己的hash函数由3个独立hash函数联立计算
- function hash($key)
- {
- // 生成3个正整数的数组,hexdec - 十六进制转十进制
- // 每个值都mod过$len
- return array(
- abs(hexdec(hash('crc32', 'm' . $key . 'a')) % $this -> len),
- abs(hexdec(hash('crc32', 'p' . $key . 'b')) % $this -> len),
- abs(hexdec(hash('crc32', 't' . $key . 'c')) % $this -> len)
- );
- }
- // 定义初始化BF长度和位数组
- function __construct($len)
- {
- $this -> len = $len;
-
- $this -> field = bitset_empty($this -> len);
- }
- // 通过载入BF文件进行初始化
- // BF文件可以通过file_put_contents('bloom',$bf->field)生成
- static function init($field)
- {
- $bf = new self(strlen(bitset_to_string($field)));
-
- $bf -> field = $field;
-
- return $bf;
- }
- // 哈希一个条目
- function add($key)
- {
- foreach ($this -> hash($key) as $h) ?bitset_incl($this -> field, $h);
- }
- // 查找条目是否在BF内
- function has($key)
- {
- foreach ($this -> hash($key) as $h) if (!bitset_in($this -> field, $h)) return false;
-
- return true;
- }
- // 计算BF假阳性率
- // $k - hash函数个数
- // $numItems - 哈希的条目数
- function falsePositiveRate($numItems)
- {
- // 因为hash函数都是独立的,故对1做hash,形成的1值应该在3个不同位置
- // 所以$k=BF自己的hash函数(1)的值=独立的hash函数个数
- $k = count($this -> hash('1'));
-
- return pow((1 - pow((1-1 / $this -> len), $k * $numItems)), $k);
- }
- }
5.资源连接
- 英文wiki:http://en.wikipedia.org/wiki/Bloom_filter
- PHP版BloomFilter实现:http://code.google.com/p/php-bloom-filter/
- PHP版Bitset包:http://pecl.php.net/package/Bitset
- 一个BloomFilter工作原理的Demo:http://la.ma.la/misc/js/bloomfilter/