前言

当我们查询一条数据时,先去查询缓存,如果缓存有就直接返回,如果没有就去查询数据库,将查询到的数据写入缓存中,然后返回。

缓存穿透

请求一条不存在的数据,永远不会命中缓存,总是会到达 db,这种现象叫缓存穿透。黑客可以利用此方案进行攻击,让服务器宕机。

方案:

  1. 如果数据库没有查到,就将查询的 key 设置为 null,放到缓存中,别忘了设置过期时间。优缺点:只能针对大量重复的 key 有效,如果每次 key 都是不通的,就会产生大量无效缓存
  2. 布隆过滤器

缓存击穿

在高并发的场景下,某一个 key 失效了,就会有大量的请求抵达数据库,这种现象叫缓存击穿。

方案:

  1. 用互斥锁,等第一个线程拿到了数据,做了缓存再解锁,后面的线程就都会走缓存了。
  2. 没有获取到缓存后,让线程 sleep(random())

缓存雪崩

某一时刻大规模缓存失效,例如缓存服务宕机,此时大量的请求抵达 db,这种现象被称为缓存雪崩

方案:

  1. 缓存集群高可用
  2. Hystrix 限流降级,例如设置每秒 200 请求,其他的请求走限流逻辑
  3. redis 开启持久化,能快速恢复重启

热点数据集中失效问题

一般缓存会有过期时间,类似的热点数据同时失效后,大量的请求会抵达 db

方案:

  1. 为了避免热点数据集中失效,可以让过期时间在基础时间上加或减去一个随机数,这样就能使失效时间错开
  2. 互斥锁
  3. 没有获取到缓存后,让线程 sleep(random())