什么是布隆过滤器以及它的作用




redis 布隆过滤器刷新_hash算法


布隆过滤器的工作原理:

  1. 将一个key通过不同的hash算法散列到不同的bit位上
  2. 当某个hash算法得到的位之前没有置位过,那么这个key肯定之前没有出现过
  3. 注意,如果某个key通过所有的hash算法得到的位之前都置位过,并不能确定这个这个key之前出现过,因为存在hash碰撞,大量key通过hash算法处理后总会有散列在相同位上的

所以布隆过滤器,顾名思义,是个过滤器,它能过滤出肯定不存在,没有出现过的key,并且随着hash算法的增多,以及bit列表长度的增加,hash碰撞的概率降低,它的误判率也会随之降低(但是永远不可能为0)

我们假设现在有6个hash算法,那么我们会有6个bit列表,假设每个bit列表占用10M内存,那么总共占用内存为60M,但是,10M代表了8000多万个bit位,6个bit列表的相互杂交,上亿的key也能轻松应对(切记,勿要忘记处理hash碰撞)

Redis中如何使用布隆过滤器

如今的互联网使用人群如此的庞大,为了支撑某个业务,我们使用的通常都是分布式的系统,因此布隆过滤器的设计也要考虑到分布式场景。

redis是我们开发中最常用的中间件,有些公司甚至直接把它当DB使用,上千G的redis集群在大公司中也经常出现。将布隆过滤器存储在redis中也是最常见的做法。

废话不多说我们直接来看代码,如何在redis中设计一个布隆过滤器

方法1:

其实很简单,redis已经给我们提供了所有的功能,lua脚本执行以及setbit指令。我们只需要设计好key就可以了。


//return 0 -------- key was not in bloom
//return 1 -------- key maybe in bloom.if need 100% correct result,then need other check,and that is not bloom's business
var bloomlua = `local r1=redis.call("SETBIT","{"..KEYS[1].."}1",ARGV[1],1)
local r2=redis.call("SETBIT","{"..KEYS[1].."}2",ARGV[2],1)
local r3=redis.call("SETBIT","{"..KEYS[1].."}3",ARGV[3],1)
local r4=redis.call("SETBIT","{"..KEYS[1].."}4",ARGV[4],1)
local r5=redis.call("SETBIT","{"..KEYS[1].."}5",ARGV[5],1)
local r6=redis.call("SETBIT","{"..KEYS[1].."}6",ARGV[6],1)
if(r1==0 or r2==0 or r3==0 or r4==0 or r5==0 or r6==0)
then
	return 0
end
return 1`

var testkey string = "testbloom"
var bitnum int64 = 8 * 1024 * 64 //64k

func main() {
	bloomkey := getbloomkey(testkey)
	index1 := hash1(testkey) % bitnum
	index2 := hash2(testkey) % bitnum
	index3 := hash3(testkey) % bitnum
	index4 := hash4(testkey) % bitnum
	index5 := hash5(testkey) % bitnum
	index6 := hash6(testkey) % bitnum

	//return 0 -------- key was not in bloom
	//return 1 -------- key maybe in bloom.if need 100% correct result,then need other check,and that is not bloom's business
	redis.EXEC("EVAL", bloomlua, 1, bloomkey, index1, index2, index3, index4, index5, index6)
}
func getbloomkey(key string) string {
	index := hash1(key)
	index = index % 100
	//one bloom use 100 bloomkeys
	//this can disperse keys to all redis servers when in cluster mode
	return fmt.Sprintf("bloom_%d", index)
}
func hash1(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}
func hash2(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}
func hash3(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}
func hash4(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}
func hash5(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}
func hash6(key string) int64 {
	var caculate int64
	//caculate
	return caculate
}


方法2:

redis在4.0版本支持了插件模式,因此有官方支持的布隆过滤器插件,只要你启动redis服务器时启用了该插件就可以使用redis插件内置的布隆过滤器指令,就像使用set,exists这样的正常redis指令一样

插件地址:


RedisBloom/RedisBloomgithub.com

redis 布隆过滤器刷新_redis 布隆过滤器刷新_02