赞
踩
我们知道HyperLogLog可以统计pv,uv的个数,其主要用到的两个命令为pfadd,pfcount。没有其他命令去判断是否包含或者是否不包含某个元素。那么会有一种场景,就类似于短视频上的推送视频,怎么做到剔除掉以前已经推送过给用户的短视频了,涉及到一个去重的问题,而在布隆过滤器中有一个exists方法,可以去判断某个元素是否已存在,而且这种方式也很省内存空间,虽说精度存在一点问题,但是这种方式可以去重!
1.我们知道布隆过滤器的命令主要为bf.add,bf.exits。bf.add和bf.exists的原理是什么呢?
2.布隆过滤器底层其实是用一个大的位数组来存储数据的,对于add进来的元素,比如add了hellojava,hellovue,hello这三个字符串,底层会调用几个hash函数,假设调用了三个hash函数,算出了hellojava对应的hash值为1,6,7,算出hello的hash值为6,7,算出hellovue的hash值为6,7,13。然后再用这几个hash值分别对位数组的长度取模,得到其在位数组上的索引位置,假设这里对位数组长度取模后仍然为原来的值,那么其结果就为如下图所示,1就代表有值,0就代表没有值,bf.exists其就是去判断位数组上某个索引位置是是否为1来判断是否存在的,但是有可能会出现误判,可以看到如下图,hello对应的索引位置上都为1,但是不代表hello这个字符串真实存在!有可能是其它元素hellovue和hellojava它们之中的某一部分而已!
1.通过docker安装
docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest
cd redis-6.2.5/
wget https://github.com/RedisBloom/RedisBloom/archive/v2.2.5.tar.gz
tar -zxvf v2.2.5.tar.gz
cd RedisBloom-2.2.5/
make
4.验证是否安装且配置布隆过滤器成功,重启redis,使用bf.add命令测试,返回1代表安装且配置布隆过滤器成功
1.bf.add/bf.madd,添加和批量添加
2.bf.exists/bf.mexists,判断是否存在和批量判断
3.使用jedis操作布隆过滤器
1)加bloom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>distribute-lock</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--json依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> <!--jedis依赖--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.2.0</version> <type>jar</type> <scope>compile</scope> </dependency> <!--bloom依赖--> <dependency> <groupId>com.redislabs</groupId> <artifactId>jrebloom</artifactId> <version>1.2.0</version> </dependency> </dependencies> </project>
2)测试
package com.yl; import io.rebloom.client.Client; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.JedisPool; public class BloomTest { public static void main(String[] args) { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); //最大空闲数 config.setMaxIdle(400); //最大连接数 config.setMaxTotal(2000); //连接最大等待时间,-1代表没有限制 config.setMaxWaitMillis(300000); /** * 配置连接池的地址,端口号,超时时间,密码 */ JedisPool jedisPool = new JedisPool(config,"192.168.244.129",6379,30000,"root123"); //获取连接对象 Client client = new Client(jedisPool); for (int i = 0; i < 10000; i++) { client.add("name","yl"+i); } //判断是否存在,有可能会出现误判 System.out.println(client.exists("name","yl7")); System.out.println(client.exists("name","1111111111111111")); } }
3)结果
1.默认情况下它的错误率是0.01,默认存储元素的总个数为100,我们可以通过bf.reserve来重新设置这两个参数。
k1代表key,0.000001代表错误率,值越少,越占内存空间,999999代表存储的元素总个数,当实际数量超出这个值时,错误率会上升。
bf.reserve k1 0.000001 999999
redis中常见的一个问题,缓存穿透又称缓存击穿,其大概意思就是存在大量一些不存在redis上的key的恶意请求,在redis中找不到数据,然后又去后台数据库查找数据也找不到,请求过多就会导致系统奔溃!
例子:假设我们要查出1亿用户的信息,首先,将它们全放在redis中,显然是不合理,那么我们如何防止缓存穿透的出现呢?
解决方案:1亿用户的信息可以放到布隆过滤器里,每当请求到布隆过滤器时,就用bf.exists方法判断某一个用户是否存在,如果该用户存在,先在redis缓存中查找该用户信息,redis中没有,再去后台数据库查找该用户信息,如果该用户压根就不是真实存在的,就没必要去后台数据库查用户信息了,这样就可以防止大量的恶意请求到后台数据库了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。