您的位置:首页 > 数据库 > Redis

关于redis中的缓存雪崩、穿透、击穿概念及解决办法

2020-03-01 11:04 549 查看

一个简单的redis的使用场景:

使用redis作为缓存的时候,大部分做法是 先在redis里查询是否有该KEY, 比如查询用户信息时,先在redis里根据用户ID查询,如果没有则到数据库里查询, 如果在数据库里查询到了再放入redis,并设置过期时间,然后返回用户数据。

该场景使用会导致以下3个问题:

1、缓存穿透:指的是redis中不存在该key, 而去查询数据库, 查到后再保存到redis, 查不到则直接返回。

这种情况看上去没毛病,正常业务操作也不会有啥问题。但是一些恶意攻击者可以使用大量不存在的key来攻击你的服务,如数据库 id 是从 1 开始的,结果攻击者发过来的请求 id 全部都是负数。这样的话,当大量不存在的key来请求你的服务时,请求每次都“视缓存于无物”,数据库接受大量的查询,达到一定的限度,这种恶意攻击场景的缓存穿透就会直接把数据库给压垮,造成其他服务不可用。

解决方式 :a、如果数据库根据该KEY未查到数据,不立即返回,先写一个空值到缓存里去,比如 set -999 UNKNOWN,并且过期时间设置小一点。这样的话,下次有相同的一个KEY来恶意访问的时候,在缓存失效之前,都可以直接从缓存中取数据,使得恶意攻击失效。 b、恶意攻击者可能使用不同的不存在的KEY来攻击,这个时候可以用过滤器来过滤掉一部分无效KEY。

2、缓存雪崩:redis中大量的KEY同时过期,或缓存机器意外发生了全盘宕机。缓存挂了,此时 大量请求全部砸向数据库,造成数据库瞬间压力增大,最终压垮数据库。

造成雪崩有两种情况: a、大量缓存设置的过期时间一致,并且也是同时初始化到缓存里的,那么同时过期也是理所当然的。 b、redis某个节点宕机,造成该节点所有key过期。

缓存雪崩的事前事中事后的解决方案
针对雪崩产生的原因a:
我们在设置过期时间的时候可以加上一个随机因子,使key过期时间分散,不同类型的KEY设置过期时间不一样。

针对雪崩产生的原因b:
事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

用户发送一个请求,系统 收到请求后,先查本地 ehcache 缓存,如果没查到再查 redis。如果 ehcache 和 redis 都没有,再查数据库,将数据库中的结果,写入 ehcache 和 redis 中。
限流组件,可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求,怎么办?走降级!可以返回一些默认的值,或者友情提示,或者空白的值。

好处:
数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。
只要数据库不死,就是说,对用户来说,一部分的请求都是可以被处理的。
只要有一部分的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。

3、缓存击穿:当某个热点KEY存在时(比如秒杀活动等),访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效过期的瞬间,全部的并发查询会落到数据库,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。

解决方式:可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。

:产生以上3个问题共同特点是给数据库造成压力,如果不查询数据库,以上3个问题就不存在了。具体做法就是使用异步程序同步缓存

  • 点赞
  • 收藏
  • 分享
  • 文章举报
mianma_YAYIZI 发布了5 篇原创文章 · 获赞 1 · 访问量 287 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: