Redis面试准备 第四天

使用缓存常见的问题有哪些?原因及其解决方案?

  1. 缓存穿透:大量请求根本不存在的key
  2. 缓存雪崩:redis中大量key集体过期
  3. 缓存击穿:redis中一个热点key过期(大量用户访问该热点key,但是热点key过期)

三者出现的根本原因:Redis命中率下降,请求直接打在DB上

         正常情况下,大量的资源请求都会被redis响应,在redis得不到响应的小部分请求才会去请求DB,这样DB的压力是非常小的,是可以正常工作的

  如果大量的请求在redis上得不到响应,那么就会导致这些请求会直接去访问DB,导致DB的压力瞬间变大而卡死或者宕机:

  1. 大量的高并发的请求打在redis上

  2. 这些请求发现redis上并没有需要请求的资源,redis命中率降低

  3. 因此这些大量的高并发请求转向DB(数据库服务器)请求对应的资源

  4. DB压力瞬间增大,直接将DB打垮,进而引发一系列“灾害”

         那么为什么redis会没有需要访问的数据呢?通过分析大致可以总结为三种情况,也就对应着redis的雪崩、穿透和击穿

问题名称缓存穿透缓存击穿缓存雪崩
资源是否存在DB数据库服务器中×
资源是否存在Redis中×××
redis没有对应资源的原因根本不存在该资源(DB也没有)某个热点key过期大部分key集体过期
根本原因大量的高并发的请求打在Redis上,但是发现Redis中并没有请求的数据,redis的命令率降低,所以这些请求就只能直接打在DB(数据库服务器)上,在大量的高并发的请求下就会导致DB直接卡死、宕机

缓存穿透

缓存穿透产生的原因:请求根本不存在的资源(DB本身就不存在,Redis更是不存在)

举例(情景在线):客户端发送大量的不可响应的请求

       当大量的客户端发出类似于:http://localhost:8080/user/19833?id=-3872 的请求,就可能导致出现缓存穿透的情况。因为数据库DB中本身就没有id=-3872的用户的数据,所以Redis也没有对应的数据,那么这些请求在redis就得不到响应,就会直接打在DB上,导致DB压力过大而卡死情景在线或宕机

解决方式:

  • 对空值进行缓存:虽然数据库中没有id=-3872的用户的数据,但是在redis中对他进行缓存(key=-3872,value=null),这样当请求到达redis的时候就会直接返回一个null的值给客户端,避免了大量无法访问的数据直接打在DB上
  • 实时监控: 对redis进行实时监控,当发现redis中的命中率下降的时候进行原因的排查,配合运维人员对访问对象和访问数据进行分析查询,从而进行黑名单的设置限制服务
  • 接口校验:用户权限的拦截,对于id=-3872这些无效访问就直接拦截,不允许这些请求到达Redis、DB上

注意事项:

  1. 使用空值作为缓存的时候,key设置的过期时间不能太长,防止占用太多redis资源
  2. 对空值缓存是一种被动的防御方式,当遇到黑客暴力请求很多不存在的数据就需要写入大量的null值到Redis中,可能导致Redis内存占用不足的情况

缓存雪崩

缓存雪崩产生的原因:redis中大量的key集体过期

举例: 当redis中的大量key集体过期,可以理解为redis中的大部分数据都被清空了(失效了),那么这时候如果有大量并发的请求来到,那么redis就无法进行有效的响应(命中率急剧下降),请求就都打到DB上了,到时DB直接崩溃

解决方式:

  1. 设置合理的缓存过期时间:将缓存中的数据的过期时间错开,避免大量数据同时过期。可以采用随机的方式设置过期时间,或者根据业务特点和数据访问模式来动态调整过期时间

  2. 实施缓存预热:在系统启动或负载较低时,提前将一些热点数据加载到缓存中。通过缓存预热,可以在缓存失效时,仍然能够从缓存中获取部分数据,减轻对底层数据源的压力

  3. 实施缓存降级策略:当缓存失效或故障时,可以选择进行缓存降级,直接返回默认值或者空值,这一部分请求将不再继续访问数据库,从而减轻数据库压力

  4. 监控和报警建立缓存监控系统【选择适合的监控工具或平台,如Prometheus、Grafana、ELK等】,实时监测缓存的状态和性能。当发现缓存异常或失效时,及时触发报警并采取相应的应对措施

缓存击穿

产生缓存雪崩的原因:redis中的某个热点key过期,但是此时有大量的用户访问该过期key

举例: 类似于“某男明星塌房事件”上了热搜,这时候大量的“粉丝”都在访问该热点事件,但是可能优于某种原因redis的这个热点key过期了,那么这时候大量高并发对于该key的请求就得不到redis的响应,那么就会将请求直接打在DB服务器上,导致整个DB瘫
解决方式:

  1. 使用互斥锁(Mutex Lock):在查询缓存数据之前,先获取一个互斥锁。当某个请求获取到锁时,其他请求需要等待,直到该请求完成并释放锁。这样可以避免多个请求同时访问底层数据源,保证只有一个请求去加载数据到缓存中

  2. 设置热点数据永不过期:对于一些热点数据,可以设置其永不过期,确保其一直存在于缓存中。这样即使缓存中的其他数据过期或失效,热点数据仍然可以被请求直接从缓存中获取,避免直接访问底层数据源

  3. 异步更新缓存当热点数据过期时,可以异步地更新缓存,而不是等待请求到来时再去加载数据。通过异步更新缓存,可以减少请求直接访问底层数据源的情况,提高系统的性能和稳定性

  4. 使用分布式锁:在分布式环境中,可以使用分布式锁来保证只有一个请求去加载数据到缓存中。通过使用分布式锁,可以避免多个节点同时访问底层数据源,减轻数据库的负载压力

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值