八、redis缓存问题和解决方案

1、redis缓存穿透

概念

缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

解决方法

1、布隆过滤器:

将数据库中所有的查询条件,放入布隆过滤器中,

当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在, 则继续查;如果判断请求查询不存在,直接丢弃。

布隆过滤器实际上上是一个二进制向量(位图)和一系列随机映射函数(哈希函数)。

布隆过滤器可以用于检索一个元素是否再一个集合中。它的优点是空间效率和查询时间都远超过一般的算法,缺点是有一定的误识别率和删除困难。

它将所有可能存在的数据通过哈希函数到放到一个足够大的bitmaps中,一个一定不存在的数据会被拦截掉,从而避免对底层存储系统的查询压力

2、缓存空对象

但是这种方法会存在两个问题:

(1)如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;

(2)即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

3、设置白名单

使用bitmaps类型定义一个可以访问的白名单,名单id作为bitmaps的偏移量,每次访问和bitmaps里面的id进行比较,如果访问id不在bitmaps里面,则不允许访问。

4、实时监控

当发现redis的命中率开始急剧降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。

2、redis缓存击穿

概念

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

解决方法

  • 预先设置热门数据

在redis高分访问之前,把一些热门数据提前存入到redis中,加大这些数据key的时长

  • 使用互斥锁(mutex key)

业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

3、redis缓存雪崩

概念

缓存雪崩是指,缓存层出现了错误,不能正常工作了(如大量key过期)。于是所有的请求都会达到存储 层,存储层的调用量会暴增,造成存储层也会挂掉的情况,(redis中也会设置数据有效时长,当大批数据数据失效时,直接访问持久层也会出现该情况)

解决方案

(1)redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台 挂掉之后其他的还可以继续工作,其实就是搭建的集群。

(2)限流降级

这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

(3)设置过期标志更新缓存

记录缓存数据是否过期(设置提前量),乳沟过期会触发通知另外的线程在后台更新实际key的缓存

(4)构建多级缓存架构

nginx缓存+redis缓存+其他缓存(chcahe等)

(5)将缓存失效时间分开

可以在原有的失效时间基础上增加一个随即值,这样每一个缓存的过期时间的重复率会降低,避免集体失效

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值