redis缓存雪崩,缓存穿透,缓存击穿

1.redis和mysql数据的关系

image-20210321115048429

2.缓存雪崩

2.1概念

当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。

a413bb958cbd7b0f1cf0646dab90b25

2.2分析

造成缓存雪崩的关键在于在同一时间大规模的key失效。第一种可能是Redis宕机,第二种可能是采用了相同的过期时间。

2.3解决方案

2.3.1在可接受的时间范围内随机设置key的过期时间,分散key的过期时间,以防止大量的key在同一时刻过期

2.3.2延长热点key的过期时间或者设置永不过期

2.3.3为了防止Redis宕机导致缓存雪崩的问题,可以搭建Redis集群,提高Redis的容灾性

3.缓存击穿

3.1概念

缓存雪崩是大规模的key失效,而缓存击穿是一个热点的Key,有大并发集中对其进行访问,突然间这个Key失效了,导致大并发全部打在数据库上,导致数据库压力剧增。这种现象就叫做缓存击穿。

image-20210321121739092

3.2分析

关键在于某个热点的key失效了,导致大并发集中打在数据库上。所以要从两个方面解决,第一是否可以考虑热点key不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量

3.3解决方案redis

3.3.1 如果业务允许的话,对于热点的key可以设置永不过期的key。

3.3.2 利用互斥锁保证同一时刻只有一个客户端可以查询底层数据库的数据,一旦查到数据就缓存至redis内,避免大量的请求穿过redis访问到底层数据库。了解互斥锁

缓存击穿

注意:在使用互斥锁的时候需要避免出现死锁或者锁过期的情况:

  • 使用前面文章介绍过的lua脚本或事务将获取锁和设置过期时间作为一个原子性操作(如:set kk vv nx px 30000),以避免出现某个客户端获取锁之后宕机导致的锁不被释放造成死锁现象;
  • 另起一个线程监控获取锁的线程的查询状态,快到锁过期时间时还没查询结束则延长锁的过期时间,避免多次查询多次锁过期造成计算资源的浪费;

4.缓存穿透

4.1概念

当查询Redis中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶意攻击时,接口的访问全部透过Redis访问数据库,而数据库中也没有这些数据,我们称这种现象为"缓存穿透"。

image-20210321123138703

4.2分析

关键在于在Redis查不到key值,这和缓存击穿有根本的区别,区别在于缓存穿透的情况是传进来的key在Redis中是不存在的。假如有黑客传进大量的不存在的key,那么大量的请求打在数据库上是很致命的问题,所以在日常开发中要对参数做好校验,一些非法的参数,不可能存在的key就直接返回错误提示。

4.3解决方案

4.3.1 在接口访问层做接口校验,如接口传参,n妙内访问次数

4.3.2 使用布隆过滤器。布隆过滤器的作用是某个 key 不存在,那么就一定不存在,它说某个 key 存在,那么很大可能是存在(存在一定的误判率)。基于布隆过滤器,我们可以先将数据库中数据的key存储在布隆过滤器的位数组中,每次客户端查询数据时先访问Redis:

  • 如果Redis内不存在该数据,则通过布隆过滤器判断数据是否在底层数据库内;

  • 如果布隆过滤器告诉我们该key在底层库内不存在,则直接返回null给客户端即可,避免了查询底层数据库的动作;

  • 如果布隆过滤器告诉我们该key极有可能在底层数据库内存在,那么将查询下推到底层数据库即可;

    布隆过滤器

参考:

https://zhuanlan.zhihu.com/p/346651831

https://cloud.tencent.com/developer/article/1666384

猜你喜欢

转载自blog.csdn.net/weixin_49298265/article/details/115049569