bloom布隆过滤器的原理和Redis的bloom过滤器的实现

       bloom过滤器它是指通过定义一定长度的数组,这个数组所有下标存储的初始值为0,然后将要存储的key值通过hash的算法获取到它的hash值,然后把这个计算出来的hash值作为数组的下标,修改该下标中的存储的值为1,表示这个key已经存储到数组中了,再下一次操作中当我们在不知道这个key是否已经存储的情况下,我们只需要通过前面的相同hash算法计算出hash值,然后通过该hash值作为下标去数组中取值,取出的值如果为0则表示不存在,可以进行新增,如果取出的值为1,则表示已经存在,不需要进行新增的操作了,这个就是bloom过滤器的基本原理。

       通过上面的bloom过滤器的原理我们也不难看出通过hash算法来计算值肯定会出现不同的key有相同的hash值的情况,我们称为hash碰撞,因此为了减少因hash碰撞造成的误判率,我们可以通过下面2种方式来最大化的减少相同hash值造成的误判率的情况:

       1.提高bloom过滤器的数组长度,因此需要更多的内存来提供。

        2.提供多个hash算法,多次进行校验,只要有1个hash算法获取到的下标处值为0就说明该key值不存在。

也因此通过上面我们也可以直接了解到bloom过滤器对key值的存在会存在一定的误判,但是对key值不存在是一定会判断出来的。同时使用bloom的另一个好处就是可以节省空间,因为它只需要存储0和1这样的bit值就可以了,不用存储很长的字符串来表示一个key的存在,因此节省了大量的空间。

       在Redis中实现了Redisbloom过滤器,它为我们提供了bloom的实现,Redisbloom是一个插件,因此需要在redis4.0.0+以上才可以支持,可以通过下面方式获取过滤器

wget https://github.com/RedisBloom/RedisBloom/archive/v2.0.0.tar.gz

下载完成后解压到指定目录,进入到解压得到的Redisbloom文件夹,通过make编译完成后可以得到一个redisbloom.so文件,然后在redis.conf文件的module部分配置如下的插件配置

#####################MODULES####################                                                                                                                      # Load modules at startup. If the server is not able to load modules
 
# it will abort. It is possible to use multiple loadmodule directives.
 
loadmodule /usr/local/redis-5.0.5/modlues/RedisBloom-2.0.0/redisbloom.so

       按照正常步骤启动Redis后我们通过下面方式验证bloom过滤器

127.0.0.1:6379> BF.ADD bloom mark
 1) (integer) 1
 127.0.0.1:6379> BF.ADD bloom redis
 1) (integer) 1
 127.0.0.1:6379> BF.EXISTS bloom mark
 (integer) 1
 127.0.0.1:6379> BF.EXISTS bloom redis
 (integer) 1
 127.0.0.1:6379> BF.EXISTS bloom nonexist
 (integer) 0
 127.0.0.1:6379> BF.EXISTS bloom que?
 (integer) 0
 127.0.0.1:6379>
 127.0.0.1:6379> BF.MADD bloom elem1 elem2 elem3
 1) (integer) 1
 2) (integer) 1
 3) (integer) 1
 127.0.0.1:6379> BF.MEXISTS bloom elem1 elem2 elem3
 1) (integer) 1
 2) (integer) 1
 3) (integer) 1

       在Java代码中我们可以通过maven的方式引入Redis的bloom客户端

<!-- RedisBloomFilter client -->
<dependency>
    <groupId>com.redislabs</groupId>
    <artifactId>jrebloom</artifactId>
    <version>1.2.0</version>
</dependency>

       初始化bloom过滤器(以下步骤可以在https://github.com/RedisBloom/JRedisBloom看到)

import io.rebloom.client.Client

Client client = new Client("localhost", 6378);

       在bloom过滤器添加1条记录

client.add("simpleBloom", "Mark");
// Does "Mark" now exist?
client.exists("simpleBloom", "Mark"); // true
client.exists("simpleBloom", "Farnsworth"); // False

       添加bloom过滤器多条记录

client.addMulti("simpleBloom", "foo", "bar", "baz", "bat", "bag");

// Check if they exist:
boolean[] rv = client.existsMulti("simpleBloom", "foo", "bar", "baz", "bat", "mark", "nonexist");

       定制一个大小为10000,误判率为0.0001的bloom过滤器

client.createFilter("specialBloom", 10000, 0.0001);
client.add("specialBloom", "foo");

      初始化一个集群客户端

Set<HostAndPort> jedisClusterNodes = new HashSet<>();
jedisClusterNodes.add(new HostAndPort("localhost", 7000));
ClusterClient cclient = new ClusterClient(jedisClusterNodes);

       验证下集群客户端

cclient.add("simpleBloom", "Mark");
// Does "Mark" now exist?
cclient.exists("simpleBloom", "Mark"); // true
cclient.exists("simpleBloom", "Farnsworth"); // False

      需要注意的情况是bloom是不支持redis sentinel哨兵集群的,它只支持单机或者cluster分片集群。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值