关于缓存需要注意的问题

学习记录关于缓存需要注意的问题。

缓存穿透

是指查询一个一定不存在的key,缓存和数据库都不会命中,因为这个数据不存在,所以永远不会被缓存,导致每次请求都会到数据库中查询。
当这个不存在的key被高并发访问时,可能导致数据库负载过大挂掉。

解决方案

  1. 使用布隆过滤器,对所有可能为空的key进行统一的存放,并在请求前做拦截。
  2. 缓存空对象,就是即使查询结果为空,也将查询结果进行缓存,避免请求穿透到数据库。为了避免数据不一致及不必要的内存占用,应该缩短缓存过期时间。

缓存击穿

是指当一些非常热点数据的key过期时,这个时间点正好被高并发请求访问,缓存不会命中,这些请求会全部穿透到数据库,瞬间压垮数据库。

解决方案

  1. 互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。

缓存雪崩

是指在同一时间,缓存key大面积过期失效,大量请求穿透到数据库,从而导致数据库崩溃,引发整个系统崩溃。上面提到的缓存穿透和缓存击穿也会导致缓存雪崩。

解决方案

  1. 给缓存的过期时间,加上一个随机值,避免集体失效。

一致性问题

一致性问题是分布式常见问题,又分为最终一致性强一致性。如果使用缓存,就一定存在不一致的问题,我们只能尽量保证最终一致性。
如果有强一致性的需求,就不要使用缓存。

解决方案

采取正确更新策略,先更新数据库,再删缓存。可能存在删除缓存失败的情况,将需要删除缓存的Key发送到消息队列中,消费者去尝试删除key
如果删除缓存失败,则让消息重新入队列,多次尝试删除缓存。

还有一种情况当数据库主库在更新数据时,主从同步没有完成,这时从库收到一个读请求,读到了旧的数据,这时候缓存存入的是旧数据,造成缓存和数据库不一致。
这种情况可以在主从同步完成后,向缓存发起删除操作,删除主从同步这段时间内缓存的数据。

缓存应该删除还是修改

大部分情况,修改缓存的成本会高于增加一次cache miss,因此应该淘汰缓存。