Redis 缓存穿透、缓存雪崩和热点 Key 问题

缓存穿透

介绍

缓存系统,按照 KEY 去查询 VALUE,当 KEY 对应的 VALUE 一定不存在的时候并对 KEY 并发请求量很大的时候,就会对后端造成很大的压力。如查询一个必然不存在的数据。比如文章表,查询一个不存在的 id,每次都会访问 DB,如果有人恶意破坏,很可能直接对 DB 造成影响。由于缓存不命中,每次都要查询持久层,从而失去缓存的意义。

解决方法

1. 缓存层缓存空值。

  • 缓存太多空值,占用更多空间。(优化:给个空值过期时间) 
  • 存储层更新代码了,缓存层还是空值。(优化:后台设置时主动删除空值,并缓存把值进去)

2. 将数据库中所有的查询条件,放到布隆过滤器中。当一个查询请求来临的时候,先经过布隆过滤器进行检查,如果请求存在这个条件中,那么继续执行,如果不在,直接丢弃。

 

缓存雪崩

介绍

又叫缓存失效。如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。缓存层宕掉后,流量会像奔逃的野牛一样,打向后端存储

解决方法

1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
2. 可以通过缓存 reload 机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存。
3. 不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
4. 做二级缓存,或者双缓存策略。A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期。

 

热点 key

介绍

由于一个缓存的构建是需要一定时间的,当一个很重要的新闻或者八卦的热点词出现时,用户的请求会在短时间内增加到很大,于是就会出现一个致命问题:在缓存失效的瞬间,有大量线程来构建缓存,造成后端负载加大,甚至可能会让系统崩溃 。

解决方法

1. 使用互斥锁(mutex key):这种解决方案思路比较简单,就是只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,重新从缓存获取数据就可以了。

2. “提前”使用互斥锁(mutex key):在 value 内部设置1个超时值(timeout1), timeout1 比实际的 memcache timeout(timeout2) 小。当从 cache 读取到 timeout1 发现它已经过期时候,马上延长 timeout1 并重新设置到 cache。然后再从数据库加载数据并设置到 cache 中。

3. "永远不过期":这里的“永远不过期”包含两层意思:

  • 从 redis 上看,确实没有设置过期时间,这就保证了,不会出现热点 key 过期问题,也就是“物理”不过期。
  • 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在 key 对应的 value 里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期。

4. 资源保护:可以做资源的隔离保护主线程池,如果把这个应用到缓存的构建也未尝不可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值