前言
当我们查询一条数据时,先去查询缓存,如果缓存有就直接返回,如果没有就去查询数据库,将查询到的数据写入缓存中,然后返回。
缓存穿透
请求一条不存在的数据,永远不会命中缓存,总是会到达 db,这种现象叫缓存穿透。黑客可以利用此方案进行攻击,让服务器宕机。
方案:
- 如果数据库没有查到,就将查询的 key 设置为 null,放到缓存中,别忘了设置过期时间。优缺点:只能针对大量重复的 key 有效,如果每次 key 都是不通的,就会产生大量无效缓存
- 布隆过滤器
缓存击穿
在高并发的场景下,某一个 key 失效了,就会有大量的请求抵达数据库,这种现象叫缓存击穿。
方案:
- 用互斥锁,等第一个线程拿到了数据,做了缓存再解锁,后面的线程就都会走缓存了。
- 没有获取到缓存后,让线程 sleep(random())
缓存雪崩
某一时刻大规模缓存失效,例如缓存服务宕机,此时大量的请求抵达 db,这种现象被称为缓存雪崩
方案:
- 缓存集群高可用
- Hystrix 限流降级,例如设置每秒 200 请求,其他的请求走限流逻辑
- redis 开启持久化,能快速恢复重启
热点数据集中失效问题
一般缓存会有过期时间,类似的热点数据同时失效后,大量的请求会抵达 db
方案:
- 为了避免热点数据集中失效,可以让过期时间在基础时间上加或减去一个随机数,这样就能使失效时间错开
- 互斥锁
- 没有获取到缓存后,让线程 sleep(random())