Redis(六)面试常问:缓存击穿,缓存穿透,缓存雪崩,分布式锁

前言

其实redis作为缓存,就是为了阻止请求进入数据库;
当缓存击穿/穿透/雪崩时,就是没有成功阻止;
所以我们解决这仨问题,就是在向怎么更好的阻止请求进入数据库.

缓存击穿

redis作为缓存使用,每个key都有自己的expire时间;
当请求的key过期时,就需要去数据库查询一边,然后把数据再放入redis;
假设一个key刚好过期的时候,有几万个请求并发访问它,那么就会同时有几万个请求去访问数据库,这就是缓存击穿问题.

怎么解决?
当从redis中找不到对应数据,查询数据库之前,加一把锁 setnx,只有拿到锁的线程才去数据库查询;拿不到锁的线程,(可以睡一定时间后)自旋再去查询redis,然后setnx.

但是这样会带来问题,第一个获取到锁的线程挂了,其他线程就永远阻塞了;
这时想到,可以给锁设置一个过期时间

这样又带来新的问题,假如过期时间设置过大,其他线程就可能多等很久;假如过期时间设置过小,第一个拿到锁的线程还没操作完呢,锁过期了,第二个线程拿到锁后又执行相同的操作
这时,可以通过多线程,第一个线程拿到锁去数据库查询后,马上再开启一个线程每隔一段时间(0.5s)去观察下,如果第一个线程没挂并且对应的该key还没更新,就把锁的expire延长一些

这样虽然代码复杂了很多,但能基本解决问题啦;
这相当于通过redis实现了一个简单的分布式协调,后面通过zookeeper实现分布式锁会好一些.

缓存穿透

假设有坏人,高并发的查询系统中根本不存在的数据,大量的请求穿透到数据库,引起性能问题.

解决方案:
布隆过滤器;

客户端实现算法和bitmap数据结构,这样客户端压力比较大;
客户端实现算法,bitmap数据放到redis,这样客户端时无状态的;
redis集成BloomModule,算法和bitmap都在redis

布隆过滤器缺点是不能删除;
如果需要删除的话,可以使用布谷鸟过滤器,或者把删除的数据对应的key,在redis存一份空value

缓存雪崩

雪崩和击穿有点像,
击穿是好多请求高并发去请求一个过期的key,(感觉发生几率略小);
雪崩是大量的key同时失效,然后很多请求进来,大量的访问数据库,(有可能是定时任务每晚12点更新缓存)

解决方案:

  1. 日常的缓存,时点性无关,过期时间加一个随机值,不让他们同时失效
  2. 如果是定时任务,比如零点更新数据,并且需要在零点后读到新的值,这时候可以像缓存击穿解决方案那样,搞个锁;
    或者在业务端控制,到零点时,延时一段时间再请求.

架构师一定要有全局感,解决高并发问题,不一定非要在最末的数据库/redis上下手
可以在任何一个环节,比如dns,lvs,nginx,JAVA服务端上下手

分布式锁

思路:

  1. setnx
  2. setnx expire 设置过期时间
  3. 守护线程延长过期时间

可以自己实现,也可以使用redission;
但最好还是通过zookeeper实现分布式锁.zookeeper没有redission快,但是它保证准确性,开发也简单.
因为已经觉得上锁了,那说名对准确度和一致性的需求 是优先于 效率的.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值