抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

缓存雪崩、缓存穿透和缓存击穿的区别是什么,各自有什么解决方案

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的Key,请求量很大,就会对后端系统造成很大的压力,这就叫做缓存穿透。

如何避免

  1. 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据Insert了之后清理缓存。
  2. 对一定不存在的key进行过滤,可以把所有的可能存在的key放到一个大的bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力,导致系统崩溃。

如何避免

  1. 在缓存失效后,通过加锁或者队列来控制数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  2. 做二级缓存,A1为原始数据,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
  3. 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀

缓存击穿

对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把DB压垮。

如何避免

  1. 使用互斥锁,当缓存失效时,不立即去load DB,先使用如Redis的setnx去设置一个互斥锁,当操作成功返回时在进行Load DB的操作并回设缓存,否则重试get缓存的方法
  2. 永远不过期:物理不过期,但逻辑过期(后台异步线程去刷新)

使用了大量缓存,那么就存在缓存击穿和缓存雪崩以及缓存一致性等问题?

缓存穿透指的是对某个一定不存在的数据进行请求,该请求将会穿透缓存到达数据库。
解决方案:对这些不存在的数据缓存一个空数据,对这类请求进行过滤。

缓存雪崩指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。
解决方案:
为了防止缓存在同一时间大面积过期导致的缓存雪崩,可以通过观察用户行为,合理设置缓存过期时间来实现;
为了防止缓存服务器宕机出现的缓存雪崩,可以使用分布式缓存,分布式缓存中每一个节点只缓存部分的数据,当某个节点宕机时可以保证其它节点的缓存仍然可用。
也可以进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。
例如:首先针对不同的缓存设置不同的过期时间,比如session缓存,在userKey这个前缀中,设置是30分钟过期,并且每次用户响应的话更新缓存时间。这样每次取session,都会延长30分钟,相对来说,就减少了缓存过期的几率

缓存一致性要求数据更新的同时缓存数据也能够实时更新。

解决方案:
在数据更新的同时立即去更新缓存,首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。
在读缓存之前先判断缓存是否是最新的,如果不是最新的先进行更新,需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。

评论