简介:
布隆过滤器是一种实现去重的思想,不属于redis,它也可以在其他地方单独使用。
布隆过滤器也是做去重的,那和Hyperloglog有什么区别.
Hyperloglog用来来估值,有偏差,它里面主要提供了两个方法:
- pfadd
- pfcount
但是没有判断是否包含的命令,例如pfexist,pfcontains这样的命令。举个例子:在刷进入头条的时候,每次推送的内容都相似,但都不一样,那有什么解决方案呢?,可以将每个用户的浏览历史记录下来,然后每次推送的时候去判断,但是这种的在高并发,数据量很大的时候就不适用。因此这里可以使用布隆过滤器去处理。
bloom Filter:是专门用来做去重操作的,它相比于缓存的话,它不那么浪费空间,但是和Hyperloglog一样都是不太精确的,但是这个精确度可以自己调节。当数据量小的时候,精确度高一点,占用的空间就多,当数据量很大的时候,可以把精确度调低一点,这样占用的空间就小一点。
bloom Filter相当于一个不太精确的set集合,我们可以使用contains方法去判断某个对象是否存在,但是这个判断不太精确,当判断不存在的时候 ,他一定不存在,当判断它存在的时候,它不一定存在。以今日头条为例,假设我们将用户的浏览记录用 B 表示,A 表示用户没有浏览的新闻,现在要给用户推送消息,先去 B 里边判断这条消息是否已经推送过,如果判断结果说没推送过(B 里边没有这条记录),那就一定没有推送过。如果判断结果说有推送过(B 里边也有可能没有这条消息),这个时候该条消息就不会推送给用户,导致用户错过该条消息。
原理:
每个布隆过滤器就相当于一个大型的位数组,和几个不同的hash函数。
所谓add操作,就是根据几个不同的hash函数元素进行hash算出一个整数索引值,拿到这个索引值后,对维数组进行取模运算,得到一个位置,每个hash函数都会得到一个位置,将位数组中对应的位置设置为1,这样就完成添加操作。
当判断元素是否存在的时候,依然对元素先进行hash运算,将运算结果和位数组的长度取模,然后在对应的位置查看是否有相应的数据,如果有,表示元素可能存在(因为有可能是其他元素存进来的),如果没有,那就一定没有。
误判的概率和位数组的大小有关,位数组越大,误判概率越小,所占用的空间就越大。
安装:
public class BloomFilter { public static void main(String[] args) { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxIdle(300); config.setMaxTotal(1000); config.setMaxWaitMillis(30000); config.setTestOnBorrow(true); JedisPool pool = new JedisPool(config, "192.168.91.128", 6379, 30000, "javaboy"); Client client = new Client(pool); //存入数据 for (int i = 0; i < 100000; i++) { client.add("name", "zl-" + i); } //检查数据是否存在 boolean exists = client.exists("name", "zl-9999999"); System.out.println(exists); } }
默认布隆过滤器的错误率是0.01,默认元素的大小为100,当然也可以存超过100个,只不过错误率会上升。
这两个参数可以去配置的:bf.reserve
应用场景:
新闻推送过滤
解决redis穿透,或者缓存击穿问题