标签:bf 元素 Filter item uint bitset bool Bloom
1。布隆过滤器原理
如何判断一个元素是否在集合中?
一般想法是将集合所有元素保存起来,然后通过查找确定。Hashtable比较合适,O(1)的平均时间复杂度,但Hashtable一个比较大的问题是空间效率,一般存储n个元素,需要2n大小空间。
而Bloom Filter实现同样的功能,使用更小的空间。
原理:
1)一个非常大的bit数组(len=m),2)一组哈希函数(size=k)
bit数组置0,将元素通过k个哈希函数计算,将bit数组相应offset置位为1。查找时,亦将元素通过k个哈希函数,分别检查offset bit位,若任一个为0,则该元素一定不存在集合中。
Bloom Filter只能用来判断不存在的情况。判断存在有false-positive,即如果检查全部是1,也不能确定是否存在。
2。应用
1)防缓存击穿,2)爬虫URL去重,3)垃圾邮件地址过滤
3。Go语言实现
实现2个函数:
type Interface interface {
Add(item []byte) // 元素加入bloom filter
Test(item []byte) bool // 检查元素是否存在
}
定义Bloom Filter数据结构:
// BloomFilter probabilistic data structure definition
type BloomFilter struct {
bitset []bool // 简单起见,使用bool数组代替bitset
k uint // hash函数个数
n uint // bloom filter中已存在元素个数
m uint // bitset长度
hashFuncs[]hash.Hash64 // hash函数数组
}
Add函数:
func (bf *BloomFilter) Add(item []byte) {
hashes := bf.hashValues(item)
i := uint(0)
for {
if i >= bf.k {
break
}
position := uint(hashes[i]) % bf.m
bf.bitset[uint(position)] = true
i+= 1
}
bf.n += 1
}
Test函数:
func (bf *BloomFilter) Test(item []byte) (exists bool) {
hashes := bf.hashValues(item)
i := uint(0)
exists = true
for {
if i >= bf.k {
break
}
position := uint(hashes[i]) % bf.m
if !bf.bitset[uint(position)] {
exists = false
break
}
i+= 1
}
return
}
4。bitset版本
上面版本使用的是伪的bitset,提高内存效率可以使用真正的bitset代替bitset []bool
https://github.com/willf/bitset
bitset []bool -> bitset.BitSet即可
另外支持分布式的Bloom Filter可以使用redis的bitmap实现。
————
前几天有个需求,检查每个用户是否第一次访问某个页面,使用了redis的Hashtable,field存shopid,真的蠢了,应该用bitmap
标签:bf,元素,Filter,item,uint,bitset,bool,Bloom 来源: https://www.cnblogs.com/gm-201705/p/10765487.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。