0%

缓存穿透-缓存雪崩-热点key

既往不恋,当下不杂,未来不迎,人生需学会放下。 —— 曾国潘

一、缓存穿透

  1. 概念

        缓存穿透是指查询一个数据库一定不存在的数据,从而导致未缓存相应的数据,最终每次请求都会访问数据库。

  1. 解决方案
    • ①用一个bitmap和n个hash函数做布隆过滤器过滤没有在缓存的键,即布隆过滤器
    • ②持久层查询不到就缓存空结果,有效时间设置较短从而保证有数据时及时更新
      • 具体是通过某个特定值key去查询数据,如果数据库中不存在则缓存肯定不存在。
      • 此时在缓存中设置此特定值key,将其对应的value设置为一个默认的值(如“NULL”),并设置一个失效时间。
      • 在当前缓存失效之前,所有通过此key的访问都被缓存挡住了。
      • 如果此key对应的数据存在时,在缓存失效之后,通过此key再去访问数据库从而设置新的value。
    • ③接口添加校验,比如用户鉴权,参数合法校验(如id<0的直接拦截等)。

二、缓存雪崩

  1. 概念

        缓存雪崩由同一时间热点缓存大面积失效,(例如:设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。

  1. 解决方案

    • ①将系统中key的缓存失效时间均匀地错开,防止统一时间点有大量的key对应的缓存失效
      • 根据业务特性设置热点数据永不过期,有更新操作的时候更新下缓存,如电商首页
    • ②优化缓存使用方式,当通过key去查询数据时,首先查询缓存,如果此时缓存中查询不到,就通过分布式锁进行加锁,取得锁的进程查DB并设置缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回缓存数据或者再次查询DB
    • ③通过队列实现串行化访问

三、热点key

  1. 概念

        热点key是指一个key非常热点(明星八卦新闻或商品大促销),大并发集中对这一个节点进行访问,当key失效的时候有大量线程来构建缓存,导致负载增加进而系统崩溃。

  1. 产生原因

    • ①用户消费的数据远大于生产的数据,如热卖商品、热点新闻等
    • ②请求分片集中,超过单 Server 的性能极限
  2. 解决方案

    • ①客户端热点key缓存:将热点key对应value并缓存在客户端本地,并且设置一个失效时间。每次读请求首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器。
    • ②将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。当通过热点key去查询数据时,通过某种hash算法随机选择一个子key,然后再去访问缓存机器,将热点分散到了多个子key上。
    • ③设置永不过期,包含两层意思:
      • redis确实没有设置过期时间,保证不会出现热点key过期问题,也就是“物理”不过期。
      • 从功能上把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期,为每个 value 设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程去构建缓存。
    • ④使用互斥锁setnx:在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用setnx去set一个mutex key,当操作成功时再进行load db的操作并设置缓存,否则就重试整个get缓存的方法。
    • ⑤异步构建缓存:缓存失效的时候另起一个线程重新构建
    • ⑥使用布隆过滤器: