缓存设计要点整理
 2018-11-10  |   146  |   MySQL  |   代码优化  redis  缓存  数据库

缓存淘汰、缓存穿透、缓存雪崩与缓存击穿

缓存淘汰

  • 缓存通常具有时效性,就是说一般缓存的数据都会有过期失效的时间
  • 缓存淘汰的策略应该是:先淘汰缓存,再读写数据库

缓存穿透

  • 含义:如果访问缓存中一定不存在的某个 key,无疑会穿透缓存,相关请求会转移到 DB,如果高并发下访问这个 key(也可能是恶意攻击),有可能导致 DB 负载过高奔溃
  • 解决办法:

    • bitmap 记录所有存在的 key:请求接入后先查询 bitmap,如果请求的 key 不存在,则直接返回空,不进入 DB
    • 缓存值为空的所有 key,缺点是可能会浪费空间

缓存雪崩

  • 定义:对于已经缓存的大量 key,如果某一时间这些键值全部过期,则请求的流量会在过期瞬间全部转移到 DB,导致数据库奔溃
  • 解决办法:

    • 缓存过期时间加随机数,保证缓存的过期时间随机分布
    • 加锁请求或将请求加入队列:保证串行请求,缺点是并发性低

缓存击穿

  • 定义:高并发访问的情况下,对于某个热点 key,在缓存过期瞬间大量请求击穿缓存直接进入 DB
  • 与缓存雪崩的区别:缓存雪崩针对大量 key 同时过期的情况,而缓存击穿则针对单个 key 被高并发访问的情形
  • 解决办法:

    • 加互斥锁(Redis 中 setnx):如果获取到缓存为空,不立即进入 DB,先获取锁,成功则进入 DB 获取数据并更新缓存,否则继续 get 缓存
    • 设置永不过期的 key
    • 额外缓存超时时间:即额外设置 value 为指定 key 的过期时间的缓存,此 value 必须小于指定键的实际过期时间,额外再开启一个线程不断检查 value 是否即将过期,如果发现 value 已经过期(此时特定的键还未过期),则马上更新 key 对于的缓存
    • 请求熔断:如果检测到 DB 请求量达到指定的上限,则拒绝访问请求
 分享: