Redis面试高频题:说说缓存穿透、击穿、雪崩

Redis是我们日常在工作中使用非常多的缓存解决手段,使用缓存,能够提升我们应用程序的性能,同时极大程度的降低数据库的压力。但如果使用不当,同样会造成许多问题,其中三大经典问题就包括了缓存穿透、缓存击穿和缓存雪崩。是不是听上去一脸懵逼?没关系,看完这篇就明白了。

缓存穿透

缓存穿透是指用户在查找一个数据时查找了一个根本不存在的数据。按照缓存设计流程,首先查询redis缓存,发现并没有这条数据,于是直接查询数据库,发现也没有,于是本次查询结果以失败告终。

当存在大量的这种请求或恶意使用不存在的数据进行访问攻击时,大量的请求将直接访问数据库,造成数据库压力甚至可能直接瘫痪。以电商商城为例,以商品id进行商品查询,这时如果使用一个不存在的id进行攻击,每次的攻击都将访问在数据库上。

来看一下应对方案:

1、缓存空对象

修改数据库写回缓存逻辑,对于缓存中不存在,数据库中也不存在的数据,我们仍然将其缓存起来,并且设置一个缓存过期时间。

如上图所示,查询数据库失败时,仍以查询的key值缓存一个空对象(key,null)。但是这么做仍然存在不少问题:

a、这时在缓存中查找这个key值时,会返回一个null的空对象。需要注意的是这个空对象可能并不是客户端需要的,所以需要对结果为空进行处理后,再返回给客户端-
b、占用redis中大量内存。因为空对象能够被缓存,redis会使用大量的内存来存储这些值为空的key-
c、如果在写缓存后数据库中存入的这个key的数据,由于缓存没有过期,取到的仍为空值,所以可能出现短暂的数据不一致问题

2、布隆过滤器

布隆过滤器是一个二进制向量,或者说二进制的数组,或者说是位(bit)数组。

因为是二进制的向量,它的每一位只能存放0或者1。当需要向布隆过滤器中添加一个数据映射时,添加的并不是原始的数据,而是使用多个不同的哈希函数生成多个哈希值,并将每个生成哈希值指向的下标位置置为1。所以,别再说从布隆过滤器中取数据啦,我们根本就没有存原始数据。

例如"Hydra"的三个哈希函数生成的下标分别为1,3,6,那么将这三位置为1,其他数据以此类推。那么这样的数据结构能够起到什么效果呢?我们可以根据这个位向量,来判断数据是否存在。

具体流程:

a、计算数据的多个哈希值;

b、判断这些bit是否为1,全部为1,则数据可能存在;

c、若其中一个或多个bit不为1,则判断数据不存在。

需要注意,布隆过滤器是存在误判的,因为随着数据存储量的增加,被置为1的bit数量也会增加,因此,有可能在查询一个并不存在的数据时,碰巧所有bit都已经被其他数据置为了1,也就是发生了哈希碰撞。因此,布隆过滤器只能做到判断数据是否可能存在,不能做到百分百的确定。

Google的guava包为我们提供了单机版的布隆过滤器实现,来看一下具体使用

首先引入maven依赖:

复制代码

1

2

3

4

5

<``dependency``>

<``groupId``>com.google.guava</``groupId``>

<``artifactId``>guava&

猜你喜欢

转载自blog.csdn.net/qq_40647372/article/details/135945628