Redis篇之缓存穿透

一、什么是缓存穿透

1.正常使用redis

        假设下面是一个根据id来查询文章的一个路径,正常流程就如下图所示。

Redis篇之缓存穿透_第1张图片

2.缓存穿透的意思

        缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库。

3.缓存穿透的实际情况

        就是别人知道了你的请求路径,参数就是在路径后面,然后别人恶意攻击你的系统,制造大量的假id去访问你的系统,由于并没有真正的数据,不会在redis里面查询,所以就会高并发的去请求数据库,可能就会导致数据库宕机,系统崩了。

二、如何解决这个问题

1.方案一:缓存空数据

        缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存。什么意思呢?就是把根据id查询不到的数据,也用redis存储null。这样的优点就是操作比较简单。缺点就是消耗内存,可能会发生数据不一致的问题。

2.方案二:布隆过滤器

        1.加入一个布隆过滤器。如下图所示:

Redis篇之缓存穿透_第2张图片

        2.布隆过滤器:一种空间效率极高的概率型数据结构,由Burton Howard Bloom在1970年提出。它主要用于判断一个元素是否可能在一个集合中,而并非确定地指出一个元素是否绝对存在。其设计思想是在有限的内存空间内快速地对大量数据进行查询以减少不必要的磁盘或网络I/O操作。

        3.工作原理:布隆过滤器是一个固定长度的位数组(通常很长)和一组独立且均匀分布的哈希函数。当一个元素加入集合时,通过这些哈希函数将该元素映射到位数组的不同位置,并将相应的位置设为1。查询一个元素是否存在时,同样使用相同的哈希函数计算其应该对应到位数组中的多个位置。如果这些位置有任何一个是0,则可以确定该元素不在集合中;但如果所有位置都是1,则认为该元素可能存在于集合中(注意:此处可能出现误报,即假阳性结果)。

        4.优点:1.空间效率高,相比于传统数据结构如哈希表等,存储相同数量的数据所需的空间更小。2.查询时间复杂度低,通常是O(1),只需执行几次哈希函数并检查位数组即可得出结论。

        5.缺点:1.有一定的误识别率(false positive rate),无法保证不存在误报。2.不支持删除操作(或者删除会导致误报率增大,除非采用复杂的变种如计数式布隆过滤器或有删除功能的布隆过滤器实现)。3.不能精确判断元素一定不在集合中(但未命中的情况下可确保元素不在集合中)。

Redis篇之缓存穿透_第3张图片

Redis篇之缓存穿透_第4张图片

        6.代码:网上代码较多,可以自行查找。

三、面试时应该如何说呢?

面试官:什么是缓存穿透 ? 怎么解决 ?

候选人

缓存穿透是指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。这种情况大概率是遭到了攻击。

解决方案的话,我们通常都会用布隆过滤器来解决它

面试官:好的,你能介绍一下布隆过滤器吗?

候选人

布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤器。

它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。

当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。

你可能感兴趣的:(缓存,redis,数据库,面试)