您的位置:首页 > 其它

缓存穿透、缓存雪崩、缓存击穿解决方法

2018-12-04 11:31 459 查看

缓存穿透:

  • 缓存穿透:查询不存在的数据,不会写入缓存,因此就会不断的去查询,在流量大的时候,数据库可能就会挂了。
  • 解决方法:
      布隆过滤器
    1. 将查询结果为空的数据写入缓存,设置过期时间短一些

缓存雪崩:

  • 缓存雪崩:大量的key设置了相同的过期时间,在某时刻全部失效,大量key请求数据库,数据库!雪崩!
  • 解决方法:在缓存过期时间上加一个随机值时间,使数据的过期时间分散,不在同一时刻失效

缓存击穿:

  • 缓存击穿:某些key在缓存将要过期的时候,碰巧有大量的并发请求这个key,这时缓存已过期,就会从数据库查询数据,大量的并发请求涌向数据库,KO!数据库败!

  • 解决方法:

      互斥锁(mutex key):访问key之前,采用SETNX(set if not exists)设置锁,来锁住后边数据的查询,然后对这个key查询数据库并设置缓存,释放锁,其他数据查询缓存

      特点:思路简单,可以保持查询结果一致性,但:代码复杂、可能死锁、线程池阻塞。

    引用:
    业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
    SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果”

    1. “提前”使用互斥锁:
      设置超时值,超时值比实际数据过期的时间值小,当从缓存中读到超时值,立马延长缓存的超时值,然后读取数据库的数据并设置缓存
      特点:一致性,缺点同互斥锁
    2. 设置缓存“永不过期”:
      如果发现要过期了,后台异步,其他数据照样输出老的值,这条数据构建缓存:从库里更新数据到缓存,返回结果
      特点:不会阻塞,但:查询结果可能不一致、每个值都要有超时值,代码复杂、多个值占用空间大
    3. 分级缓存:
      一级缓存、二级缓存,一级缓存失效时间短。
      先请求一级,如果一级失效未查询到则加锁,然后从数据库读取数据更新到一级、二级缓存中,在此期间,其他的数据请求二级缓存
      特点:不阻塞,但:会占用额外的缓存空间、查询结果可能不一致
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: