乐趣区

关于redis:面试Redis缓存并发-缓存雪崩-缓存穿透

本文次要叙述缓存并发,缓存雪崩,缓存穿透的问题以及解决方案。

缓存并发

什么是缓存并发

场景:在你每天刷抖音,看微信短视频时,都会有一个评论列表,在评论列表中,查问评论的时候,会先去查问 Redis 缓存,如果有,就立刻返回;如果没,就去数据库查问数据,接着更新缓存,返回数据。这时候,如果访问量十分多,有多个 C 端同时查问评论,Redis 缓存又恰好没缓存数据,此时,多个 C 端就会同时去查询数据库。上述这种景象,就被称为缓存并发。

话说回来,缓存并发会带来什么危害

  • 让数据库的压力剧增,因为数据库抗不了高并发,流量再大一点,能够间接被打垮,对用户极其不敌对,在现在互联网上,App 利用的被代替率是很高的,稍有不慎,用户就会被其余 App 抢走,这对企业来说是灾难性的。咱们能够晓得,Redis 这玩意儿,要么不出问题,一出问题,必定是大问题。这也就是为什么要强调知其然知其所以然的起因。

既然咱们曾经晓得缓存并发的的严重性,那如何解决

  • 要解决问题前,咱们得剖析问题为何会产生。絮叨一下,很多人无论是在面试时或者工作时,遇到问题,就立马改,或者说依照百度给的办法就套上去试,这个不行,试那个。这种解决问题的形式是不正确的。个别解决问题的方法论是:遇到报错——定位问题——剖析问题——设计解决方案——解决问题。回到缓存并发问题上,咱们剖析一下“为什么呈现缓存并发”。

为什么会缓存并发

  • 起因一:在高并发场景下,机器刚刚启动,且没预热缓存,缓存都为空,又没用分布式锁
  • 起因二:在高并发场景下,机器运行已运行一段时间,但缓存刚好生效,又没用分布式锁
  • 起因三:在高并发场景下,Redis 宕机了

以上 3 种起因都会产生缓存并发,如有脱漏其余起因,欢送各位同学在留言区补充。

晓得起因后,咱们能够对照起因来设计解决方案了。

解决方案

  • 针对起因一和起因二,计划:分布式锁。这个容许一个线程去申请数据库,其余线程挂起,线程查完数据库后,更新缓存,其余线程去拜访缓存,返回数据。至于分布式锁如何应用和其底层实现,其实有比拟多的细节留神的,但这里不过多解说,后续会陆续出对应的文章,如果你安耐不住寂寞,能够去谷歌一下。
  • 针对起因三,计划:Redis 的高可用。说到高可用,无非就是主从构造 + 哨兵模式,或者 Redis 集群。(加链接)

分布式锁和 Redis 高可用,其实是预防措施,这些应该是事先工作。如果当初缓存并发的确曾经产生了,能做的就是把这个模块服务的流量入口放大,免得因这个模块服务流量过大把 MySQL 间接打死,从而导致其余模块服务受到影响。如果是 Redis 宕机了,先把流量入口放大,而后连忙重启机器。

当然,最好是事先做好 Hystrix 的限流、降级、拒绝服务等工作。限流和降级,限流,顾名思义就是限度流量,容许多少流量能够通过,比方每秒最多 1000。超过 1000 后的申请,就走降级,比方返回一些默认值或者情谊提醒:目前零碎忙碌,稍后重试。拒绝服务,则是最初一道防线,如果流量继续一段时间后,依然很大,就间接拒绝服务,拒绝服务是为了爱护 Redis 间接被流量一波带走,如果 Redis 服务被打死后,复原是比拟消耗工夫的,而且也会因为流量始终很大,刚重启,流量一波又间接带走 Redis,实现双杀,Double Kill。拒绝服务,会等流量小后,较快复原回失常服务状态。拒绝服务是无可奈何之举。

当初大头菜初入互联网行业时,老马识途,什么也不懂,用 Redis 前,只晓得 Redis 很厉害,很适宜做缓存,对于 Redis 的注意事项,除了晓得在生产环境不能用 keys * 命令外,其余一律不懂。过后的评论我的项目,因为流量特地大,并发贼高,查问评论接口就呈现了缓存并发问题,幸好提前做了默认值回复和限流 + 降级措施。上面是用分布式锁解决缓存并发的要害代码:

  @Autowired
  private DistributionLock locker;
  
 // 没缓存,查数据库,获取评论
  if (comment == null) {
      // 加分布式锁,只容许一个线程去回源
      if(locker.trylock(Constants.QUERYCOMMENT+moduleType+resourceId)){
          try {comment = getDataFromRedis(moduleType, resourceId);
              if(comment == null){
                  // 缓存没数据,去数据库查
                  comment = getDataFromMongoDB(moduleType, resourceId);
              }
          }finally {locker.unlock(Constants.QUERYCOMMENT+moduleType+resourceId);
          }
      }

接下来,持续讲缓存穿透

缓存穿透

什么是缓存穿透

场景:查问评论的时候,如果间接查问 id=- 1 的数据,那么在缓存中,没命中,又去数据库中查找,又没命中。上述这种状况,被称为缓存穿透。用通俗易懂的话来概括:就是查找一个肯定不存在数据库的数据,就叫缓存穿透。

那缓存穿透有什么害处呢

  • 如果流量大时,会间接打趴服务,造成服务不可用。

依照方法论的套路持续走

为什么会呈现缓存穿透

  • 起因一,非正常申请,比方:黑客攻击,专门结构一些非凡格局的数据来申请,给零碎造成微小压力。
  • 起因二,失常申请,用户输错了数据。

解决方案

  • 计划一:缓存空对象:在申请时,先拜访缓存,查不到数据,再去数据库查问,数据库也查不到对应的数据,返回 null 给客户端。且异步更新缓存 (key,“null”),并退出短暂的过期工夫。

  • 计划二:计划一其实有一个显著的毛病,就是如果申请的数据肯定不存在时,那么这个时候,缓存就缓存一大堆无用的(key1,”null”),(key2,”null”)。节约内存。这个时候能够联合数据校验和布隆过滤器。

说到数据校验,这个事儿是特地重要的。尤其是在一些间接波及到钱的服务中,数据校验是巨重要的。如果不进行数据校验,大公司的老板就少一台宾利。小公司,就可能间接破产了。上面是大头菜的同学所在公司的案例

不论如何,造就良好的开发习惯,能让你受害一生。

缓存雪崩

什么是缓存雪崩

场景:在评论列表中,如果有一批评论成为了热点评论,但可怜,此时这批条评论,在 Redis 缓存中,都生效了,因为没命中缓存,加上大量申请,都去数据库查问评论,从而给数据库造成极大压力,甚至解体。这种状况,被称为缓存雪崩。

缓存雪崩的害处

给数据库极大压力,甚至打垮数据库,从而造成零碎不能失常提供服务。

为什么会缓存雪崩

  • 起因一,redis 宕机,相当于多个 key 同一时刻生效。
  • 起因二,redis 没宕机,多个 key 失常到时就生效。

总结:如何你面试的时候,遇到这个问题,最好分状况答复,就是 redis 是否宕机。给面试官留下脑子清晰的印象。

解决方案

  • 计划一,解决起因一,既然宕机了,那就想到高可用,redis 集群,哨兵模式,故障转移和故障复原,同时还应该做好监控和报警。如果没法主动实现故障转移,那就人工干预。
  • 计划二,过期工夫 = 生效工夫 + 随机工夫,解决起因二。
  • 计划三,永不过期,既然你是因为过期工夫到了导致的雪崩,那就罗唆让你不过期就完事了。有人会问,那缓存一致性怎么保障?后盾被动更新:就是通过 mysql 更新的时候,让 mq 监听 Binlog,回调更新缓存。使其缓存和数据库数据保持一致。
  • 计划四,能够从利用架构角度登程,通过限流,降级,熔断伎俩来升高影响,除此之外来防止多级缓存来防止这种劫难。如果你应用的微服务架构是 SpringCloud,那你能够间接应用 Hystrix,来实现限流,降级,熔断,批改一下配置文件即可。

补充

缓存击穿,就是只有一个 key 过期的缓存雪崩。

总结

全篇下来,简直都是依照遇到报错——定位问题——剖析问题——设计解决方案——解决问题方法论来写的。文中介绍了缓存并发,缓存穿透,缓存雪崩的定义,危险,起因,解决方案。大头菜心愿你读完这篇文章后,不仅能学会常识,更能把握定位问题——剖析问题——解决问题的方法论。知识点,这些当前可能会忘,但办法把握好后,方能见招拆招。

非常感谢你能看到这里,如果感觉文章写得不错 求关注 求点赞 求分享 (对我十分十分有用)。
如果你感觉文章有待进步,我非常期待你对我的倡议,求留言。
如果你心愿看到什么内容,我非常期待你的留言。
各位的捧场和反对,是我创作的最大能源!

退出移动版