redis 缓存穿透,缓存击穿,缓存雪崩 的理解(转载的文章一定要看)

首先缓存的原理:

  我认为缓存的原理就是在每次先db查询一个value值时,先查询缓存,如果缓存没有再去差db,如果db有,就返回查询结果,同时再把这个结果再存到缓存中

1、缓存穿透

  当一个key值在数据库中不存在时,我们每次访问查询这个key的时候,由于缓存中肯定没有值,所以每次都需要去查询一下数据源,这样就很有可能导致数据员所在的服务器压力过大;例如,如果黑客利用不存在的用户id去不断的获取改用户的信息,则很容易导致数据库崩溃

2、缓存击穿

  当一个key值在数据库中存在,但是过期了,这个时候如果有大量的请求过来,这些请求发现缓存过期了,就会大量的去访问db,将放回的数据设置到缓存中,这个时的大量并发很可能导致数据库崩溃

3、缓存雪崩

  在缓存重启或者在某个时间段内出现大量的缓存过期或者大量的key在数据库中不在的情况时,出现的数据库崩溃。

缓存穿透 解决方式:

1、布隆过滤器

  原理:将所有可能的数据存储到一个很大的bitmap去存储有多个哈希函数计数出key值(也就是说一个value可能存在多个地方),这样,我们就可以过滤一定不存在的值,这样就避免存储系统的对数据库的压力(通过布隆过滤器我们可以判断一个key肯定不存在value,或者说可能存在value值

2、查询时,不管时value不存在还是数据库崩溃,我们都将这个不存在的key,也设置一个默认的value值存入缓存中,但是注意,它的缓存时间设置很短,一般不会超过5分钟

缓存击穿 解决方式:

1、使用互斥锁(mutex key)

  业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

 缓存雪崩的解决方案

1、加锁或者设置队列的方式,反之同一时间的失效或者无效的db访问

  大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上

2、随机设置失效时间

  还有一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

参考文章:https://www.cnblogs.com/xichji/p/11286443.html

https://www.jianshu.com/p/2104d11ee0a2

原文地址:https://www.cnblogs.com/jiazhutao/p/12771417.html