关注公众号 不爱总结的麦穗 将不定期推送技术好文
在实际高并发场景下,稍有不慎,就会造成缓存穿透、缓存击穿和缓存雪崩的问题。那什么是缓存穿 透?什么是缓存击穿,又什么是缓存雪崩呢?它们是如何造成的?又该如何解决呢?
缓存穿透
什么是缓存穿透呢?
如果在请求数据时,在缓存层和数据库层都没有找到符合条件的数据,也就是说,在缓存层和数据库层都没有命中数据,这种就叫作缓存穿透。
造成缓存穿透的原因
查询某个Key对应的数据,Redis缓存中没有相应的数据,则直接到数据库中查询。数据库中也不存在,数据库则会返回空。这就造成每次通过这样的Key去查询数据都会直接到数据库中查询。
如何解决缓存穿透问题
应对缓存穿透的方案,常见的方案有以下几种。
- 缓存空值或者默认值
当我们发现缓存穿透的现象时,可以针对查询的数据,在缓存中设置一个空值或者默认值,这样后续请求就可以从缓存中读取到空值或者默认值返回,而不会继续查询数据库。
- 布隆过滤器
布隆过滤器可以针对大数据量的、有规律的键值进行处理。一条记录是不是存在,本质上是一个Bool值,只需要使用1bit就可以存储。我们可以在写入数据库数据时,使用布隆过滤器做个标记,当用户请求到来时,以通过查询布隆过滤器快速判断数据是否存在,如果不存在,就不用去查询数据库了。这样大量请求只会查询 Redis 和布隆过滤器,而不会查询数据库。
布隆过滤器认为不在的,一定不会在集合中;布隆过滤器认为在的,可能在也可能不在集合中。
缓存击穿
什么是缓存击穿?
如果缓存中的数据在某个时刻批量过期,导致大部分用户的请求都会直接落在数据库上,这种就叫作缓存击穿
造成缓存击穿的原因
如果我们为缓存中的大部分热点数据(如秒杀活动,这类被频地访问的数据被称为热点数据)设置了相同的过期时间,则到了某一时刻,缓存中的热点数据就会批量过期。此时大量的请求访问热点数据,就无法从缓存中读取,从而直接访问数据库,数据库就很容易就被高并发的请求冲垮。
如何解决缓存击穿问题
应对缓存穿透的方案,常见的方案有以下几种。
- 热点数据永不过期
对于比较热点的数据,我们可以在缓存中设置这些数据永不过期(把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的更新)。对于其他的缓存项分配比较合理的过期时间,避免同一时刻失效。
- 互斥锁
先获取分布式锁,获取锁成功才执行数据库查询和写数据到缓存的操作,获取锁失败,则说明当前有线程在执行数据库查询操作,当前线程睡眠一段时间在重试(只让一个请求去数据库读取数据)。
缓存雪崩
什么是缓存雪崩?
大量的请求无法在缓存系统中处理,请求全部打到数据库,导致数据库压力激增,甚至宕机,这种就叫作缓存雪崩
造成缓存雪崩的原因
-
缓存系统出现故障,所有的并发流量直接到达数据库
-
如果在某一时刻缓存集中失效,所有的并发流量就会直接到达数据库。数据存储层的调用量就会暴增
如何解决缓存雪崩问题
应对缓存穿透的方案,常见的方案有以下几种。
- 过期时间添加随机值
要避免给大量的数据设置一样的过期时间,让缓存失效的时间点尽量均匀。
- 互斥锁
先获取分布式锁,获取锁成功才执行数据库查询和写数据到缓存的操作,获取锁失败,则说明当前有线程在执行数据库查询操作,当前线程睡眠一段时间在重试(只让一个请求去数据库读取数据)。
- 接口限流
我们在业务系统的请求入口处控制每秒进入系统的请求数,避免过多的请求被发送到数据库。
- 缓存的高可用
现在使用的缓存,大多是通过Redis来实现的,保证Redis的高可用,将Redis缓存部署成高可用集群,可以有效的防止由于缓存宕机导致缓存雪崩问题的发生。
- 缓存降级
缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据。
缓存预热
缓存预热就是系统上线时,将相关的缓存数据直接加载到缓存系统,这样就可以避免在用户请求的时候,先查询数据库,然后再将数据回写到缓存。
总结
本文分别讲述了各自的产生原因和解决方法,本文分别讲述了各自的产生原因和解决方法。