9.Redis - 缓存击穿,穿透,雪崩解决方案

Redis - 缓存穿透,击穿,雪崩解决方案

缓存击穿

在这里插入图片描述
在微服务项目中,我们会有很多的Client去访问redis,这些Client就是我们写的service。因为业务需求,service会去访问作为缓存的redis(缓存一些热数据),而在redis后面还有数据库(MySQL)。
而这些服务可能会被其他的service调用,组成了一个微服务群体,再往前就是Nginx反向代理 负载均衡服务器或者 LVS服务器,再Nginx或者LVS之前就是互联网上面的用户。

在整个互联网项目中,用户是造成所有行为的一端,如果用户这一端流量很大,产生了高并发。

假如有10W并发,经过项目中的微服务(freemarker,redis,solr等技术),最后抵达mysql 可能只有几千,甚至几百。其中redis作为缓存有极其重要的阻截作用!

redis作为缓存 着重点 有两个:

  1. key的过期时间,没有用户访问的情况下,经过一定的时间,销毁数据(淘汰冷数据)。
  2. 开启淘汰策略(LRU、LFU),redis内存满了之后,淘汰一批相对使用次数少 或者 较久没有使用的数据。

正是因为作为缓存的数据会过期,所以才会产生击穿,雪崩的问题。

那么击穿是怎么回事呢?
就是在redis中某个数据刚刚 过期 淘汰 的瞬间,用大量的用户一起访问这个数据,产生 高并发。这个时候redis返回的是null,相当于在redis缓存上打了一个窟窿,这些请求就都会去访问数据库,这就是缓存击穿。

解决思路:
问题根本在于一瞬间有大量的并发请求命中数据库,命中的原因是redis中没有key,那么怎么阻止请求并发到达数据库?
首先redis是单进程单实例的,并发请求到达redis的时候会串行化,那么肯定会有第一个请求先到达redis而没有找到缓存数据。
第一个请求没有拿到数据回到service后,调用redis的 setnx 命令在redis中创建key。setnx 命令只能创建key,如果key不存在,则能创建成功;如果key已经存在,则返回null(分布式锁)。获得锁的请求去访问mysql数据库返回从新把数据缓存进redis,没有获得锁的请求死循环尝试在redis中获取数据,中途可以sleep一定的时间(sleep不能太久,服务链会超时),sleep结束后重复在redis中获取缓存数据,尝试获得锁的过程,直到获得数据跳出循环。
但是这么做会不会有bug ?
可能会产生 死锁 的问题! 如果去访问数据库的请求挂了,setnx得不到释放,后续请求也无法获取到锁,那些请求就会一直循环sleep。怎么解决呢? 可以设置setnx的过期时间。
即使把锁设置了过期时间,依然会有bug:
第一个去请求数据库的请求可能没有挂,只是因为在mysql这里出现了拥塞,导致锁过期超时。
这样就会引起连锁反应,第二个请求拿到了锁,同样到达mysql发生拥塞,就会可能导致访问数据库的请求越堆越多。甚至第一个请求从mysql拿到数据后返回给redis,后续请求从redis拿到数据返回,但是之前拿到锁的请求可能还在mysql排队,或者引起一些用户访问丢失。
这种情况下,可以利用多线程,一个线程去mysql取数据,另外一个线程监控数据是否取回来,并且及时更新锁的过期时间。

缓存雪崩

在这里插入图片描述
缓存雪崩是缓存击穿的加强版。
它俩的区别是
击穿是某个缓存数据 过期淘汰,并且非常巧的对这个数据有高并发访问,
而雪崩是大量的缓存数据 同时 过期淘汰,比如:某些业务要求缓存数据 凌晨0点 数据过期,需要从新加载新的数据到缓存,间接造成大量的访问命中数据库。

如何解决?

  1. 普通场合: 普通场合: 普通场合:
    随机过期时间。但是随机过期时间不适合 要求凌晨0数据过期 的场合。
  2. 缓存 12 点必须过期: 缓存12点必须过期: 缓存12点必须过期:
    强依赖缓存击穿方案。并发时,第一个请求获得锁请求数据库,后续数据获得锁失败 -> 休眠 -> 再次尝试获得数据 -> 获取失败循环 -> 获取成功跳出循环。
    或者使用0点延迟方案。就是在0点的时候,前置服务里面加一个随机sleep(几十毫秒),保证了请求到达redis时间的差异。(或者 强依赖缓存击穿方案 和 0点延迟方案一起使用)
  3. 秒杀场景:监控缓存过期时间,提前出发缓存的延期。

缓存穿透

在这里插入图片描述
还是前边业务的调用某一个service,而这个service调用redis缓存。
而穿透的概念就是 从前边业务查询的数据是在系统中不存在的数据,即 redis 没有,mysql里也没有。这会使每次请求都命中数据库。
解决办法:布隆过滤器。
请见 : https://blog.csdn.net/xi_rurensheng/article/details/106547989

不通过滤器的缺点:
在大量增删改的操作下,布隆过滤器 只能增加不能删除。
解决:删除操作再删除数据库的情况下,同时把缓存中的数据置空。或者换一个过滤器(布谷鸟过滤器)。

拓展:redis分布式锁

实现: setnx
弊端:过期时间。

  1. 时间到了,活还没做完,别人又去干了。
  2. 过期时间没到, 自己挂了。

解决弊端: 多线程,延长过期。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值