什么是缓存雪崩?怎么解决?
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期或宕机了,很多数据都查不到从而查数据库。
如何解决呢?
什么是缓存穿透?怎么解决?
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
如何解决呢?
什么是缓存击穿?怎么解决?
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
如何解决呢?
什么是缓存并发竞争?怎么解决?
多个客户端写一个 key,如果顺序错了,数据就不对了。但是顺序我们无法控制。
如何解决呢?
使用分布式锁,例如 zk,同时加入数据的时间戳。同一时刻,只有抢到锁的客户端才能写入,同时,写入时,比较当前数据的时间戳和缓存中数据的时间戳。
什么是缓存和数据库双写不一致?怎么解决?
连续写数据库和缓存,但是操作期间,出现并发了,数据不一致了。
通常,更新缓存和数据库有以下几种顺序:
先更新数据库,再更新缓存。
先删缓存,再更新数据库。
先更新数据库,再删除缓存。
先更新数据库,再更新缓存
这么做的问题是:当有 2 个请求同时更新数据,那么如果不使用分布式锁,将无法控制最后缓存的值到底是多少。也就是并发写的时候有问题。
先删缓存,再更新数据库
这么做的问题:如果在删除缓存后,有客户端读数据,将可能读到旧数据,并有可能设置到缓存中,导致缓存中的数据一直是老数据。
解决方案:延时双删策略,可将1秒内缓存脏数据,再次删除。最后一步的删除通常是异步操作,就是防止有客户端读取的时候设置了旧值。
先更新数据库,再删除缓存
这个实际是常用的方案,但是有很多人不知道,这里介绍一下,这个叫 Cache Aside Pattern,老外发明的。如果先更新数据库,再删除缓存,那么就会出现更新数据库之前有瞬间数据不是很及时。
同时,如果在更新之前,缓存刚好失效了,读客户端有可能读到旧值,然后在写客户端删除结束后再次设置了旧值,非常巧合的情况。
有 2 个前提条件:缓存在写之前的时候失效,同时,在写客户端删除操作结束后,放置旧数据 —— 也就是读比写慢。甚至有的写操作还会锁表。
所以,这个很难出现,但是如果出现了怎么办?使用双删!!!记录更新期间有没有客户端读数据库,如果有,在更新完数据库之后,执行延迟删除。
还有一种可能,如果执行更新数据库,准备执行删除缓存时,服务挂了,执行删除失败怎么办???
这就坑了!!!不过可以通过订阅数据库的 binlog 来删除。