本文共 1420 字,大约阅读时间需要 4 分钟。
本文是预防缓存穿透,并不是预防缓存击穿,缓存击穿需要自己写同步方法,这里不多说缓存击穿问题,
一种是通过保存null值,和提前限制条件,来确保不会出现缓存穿透,这种方式在黑客随机访问的情况下,会不停的保存不必要的null值,redis内存使用会浪费很多。一种是使用过滤器算法,先去判断数据是否真的存在。
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。(百度百科)
一说到布隆过滤器很多小伙伴就会说到redis,其实布隆过滤器和redis没有什么关系,它只是一种算法,最直白的理解:通过多个Hash函数将一个元素映射成一个位阵列(Bit array)中的一些点。我们只要看看这些点是不是1就可以知道集合中有没有它了。
讲了这么多,在实际项目中使用才是重点,如果是单机项目,可以用guava 实现好的bloomfilter,但是本文肯定不是说单机的。
比如在某一个service对数据库进行写入的时候,我们可以调用布隆过滤器同时写入,这样在获取的时候,就可以先在过滤器内进行判断,是否存在这个数据。
第一种实现方式是:redis4.0 + 安装bloomfilter插件,通过调用bf命令来设置或判断。
第二种实现方式:本机运算bit矩阵,然后通过pipe multi 向redis发送批量的setbit命令,获取的时候同样是本机运算,批量的getbit来判断。
二者的区别是
第一种方式用起来很简单,装个插件,写个execute就完事了,但是运算是在redis服务器上。第二种方式主要计算在本机,redis只负责setbit和getbit,没有运算过程。 注意:第二种方式如果是分布式应用,不要使用guavaCache,因为内存信息是在本机,并不在redis,一致性有问题。
还有最重要的一点,布隆过滤器在使用的时候,只能添加,不能删除,也就是说只适合不会被删除的数据做判断。
如果对数据有删除的操作,请使用Cuckoo Filter
简单的说一下吧,它和布隆过滤器相比,做了哪些改进,它的算法实现方式是,会计算出2个hash,分别映射到两个位置,一个是记录的位置,另一个是备用位置。这解决了布隆算法中误报的问题。
Cuckoo的哈希函数是成对的(具体的实现可以根据需求设计),每一个元素都是两个,备用位置是处理碰撞时用的。
当两个哈希位置有一个为空时,则插入该空位置;
当两个哈希位置均不为空时,随机选择两者之一的位置上key 踢出,并计算踢出的key 在另一个哈希值对应的位置,若为空直接插入,不为空踢出原元素插入,再对被踢出的元素重新计算,重复该过程,直到有空位置为止。Cockoo hashing 有两种变形:一种通过增加哈希函数进一步提高空间利用率;另一种是增加哈希表,每个哈希函数对应一个哈希表,每次选择多个张表中空余位置进行放置,三个哈希表可以达到80% 的空间利用率。
Cockoo hashing 的过程可能因为反复踢出无限循环下去,这时候就需要进行一次循环踢出的限制,超过限制则认为需要添加新的哈希函数。
转载地址:http://jxlsi.baihongyu.com/