Redis缓存问题排查

一.缓存穿透

  概念:缓存穿透是指查询的数据不存在,redis和mysql(或其他持久存储的数据库)都不能命中。工作中出于容错的考虑,如果从数据库内不能查到数据则不会写入缓存,缓存穿透将导致不存在的数据每次请求都要到数据库去查询,失去了缓存存在的意义(保护后端数据持久存储,例:数据库)

  问题影响缓存穿透问题可能会加大后端存储负载,由于很多后端持久层不具备高并发性,甚至可能造成后端存储宕机。通常可以在程序中统计总调用数、缓存层命中数、如果同一个Key的缓存命中率很低,可能就是出现了缓存穿透问题

 

     问题原因:造成缓存穿透的基本原因主要有两个。

  第一. 自身业务代码或者数据出现问题(例如:set 和 get 的key不一致)

  第二. 一些恶意攻击、爬虫等造成大量空命中(爬取线上商城商品数据,超大循环递增商品的ID)
  解决方案:

  1. 缓存空对象:是指在持久层没有命中的情况下,对key进行set (key,null)

       缓存空对象会有两个问题:

    第一,value为null 不代表不占用内存空间,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。

    第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为5分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象

  2. 布隆过滤器拦截

        在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截,当收到一个对key请求时先用布隆过滤器验证是key否存在,如果存在在进入缓存层、存储层。可以使用bitmap做布隆过滤器。这种方法适用于数据命中不高、数据相对固定、实时性低的应用场景,代码维护较为复杂,但是缓存空间占用少。

        布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

    两种方案对比:

      缓存控对象:适用于数据命中不高,数据频繁变化实时性高(代码维护简单,需要的缓存空间较多,数据不一致)

      布隆过滤器:适用于数据命中不高,数据相对固定实时性低(代码维护复杂,需要的缓存空间较少)

二.缓存雪崩

  由于缓存层承载着大量请求,有效地保护了存储层,但是如果缓存层由于某些原因不可用(宕机)或者大量缓存由于超时时间相同在同一时间段失效(大批key失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩

  解决方案:
  可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。
  采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底
  缓存的过期时间用随机值,尽量让不同的key的过期时间不同(例如:定时任务新建大批量key,设置的过期时间相同会导致其同时过期)

三.缓存击穿
  系统中存在以下两个问题时需要引起注意:在缓存失效的瞬间,有大量线程来重建缓存,造成后端负载加大,甚至可能会让应用崩溃。

    1.当前key是一个热点key(例如一个秒杀活动),并发量非常大。
    2.重建缓存不能在短时间完成,可能是一个复杂计算,例如复杂的SQL、多次IO、多个依赖等。
   解决方案:

  1. 分布式互斥锁

        只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。set(key,value,timeout)
   2. 永不过期

    •   从缓存层面来看,确实没有设置过期时间,所以不会出现热点key过期后产生的问题,也就是“物理”不过期。
    •   从功能层面来看,为每个value设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程去更新缓

    两种方案对比:

    分布式互斥锁:这种方案思路比较简单,但是存在一定的隐患,如果在查询数据库 + 和 重建缓存(key失效后进行了大量的计算)时间过长,也可能会存在死锁和线程池阻塞的风险,高并发情景下吞吐量会大大降低!但是这种方法能够较好地降低后端存储负载,并在一致性上做得比较好。

    “永远不过期”:这种方案由于没有设置真正的过期时间,实际上已经不存在热点key产生的一系列危害,但是会存在数据不一致的情况,同时代码复杂度会增大。

 

posted @ 2021-05-14 15:19  木易-故事里的人  阅读(76)  评论(0编辑  收藏  举报