缓存雪崩
描述
缓存在同一时间出现大规模的key失效,进而请求db加载最新数据,导致db压力过大,甚者可能导致db宕机。导致key失效的场景:
-
redis宕机
; -
缓存key过期时间一致,同时到期失效
;
解决方案
过期时间一致问题/redis宕机
- 均匀过期:设置不同的过期时间;
- 分级缓存:不同层级使用不同的过期时间;
- 热点数据缓存永不过期;
a.物理不过期,针对热点key不设置过期时间;
b.逻辑过期,将过期时间存在对应的value上,通过异步程序监控、同步更新缓存值; - 保证Redis缓存的高可用,防止Redis宕机导致缓存雪崩的问题。可以使用 主从+ 哨兵,Redis集群来避免 Redis 全盘崩溃的情况。
缓存雪崩发生,缓解措施
- 通过互斥锁,控制缓存的重新写入;
redis.setnx("lock_key", value)
redis.setnx
:当缓存lock_key
不存在时,设置lock_key
值为value
,方法返回结果1
,反之返回0
;
即当成功构建lock_key
缓存时,其他同步线程访问将会阻塞,保证同一场景同一时间
只有一个线程可以执行db load
操作,并写入缓存;
- 使用熔断机制,限流降;
- redis宕机,重启redis,尽快同步恢复缓存数据;
缓存击穿
描述
单个key缓存失效,并发请求导致db压力过大,与缓存雪崩
相似,区别在于雪崩
时大批key缓存失效,穿透
则时单个key失效
解决方案
- 通过互斥锁,控制
db.load
以及缓存的重新写入; - 热点数据永不过期(同雪崩一致);
缓存穿透
描述
与缓存击穿
的区别在于,缓存击穿
是缓存失效,但是db
能够加载到数据资源,而缓存穿透
则是缓存未找到,db
也查询不到资源。这样每次访问缓存,都会去db加载一次不存在的数据
。当有大量并发访问不存在的数据
时,就会造成db压力过大,进而导致db崩溃;
解决方案
- 第一次读取缓存不存在,db查询不存在后,将key设置空值、短过期时间,缓存至redis中。这样做的好处就是,同一时间大量访问
不能存在数据
时,能从缓存直接返回控制;缺点就是不存在数据
key多种多样时,redis就会存储了一批没用的数据,占用内存; - 布隆过滤器。如果布隆过滤器判定某个 key 不存在布隆过滤器中,那么就一定不存在,如果判定某个 key 存在,那么很大可能是存在(存在一定的误判率)。于是我们可以在缓存之前再加一个布隆过滤器,将数据库中的所有key都存储在布隆过滤器中,在查询Redis前先去布隆过滤器查询 key 是否存在,如果不存在就直接返回,不让其访问数据库,从而避免了对底层存储系统的查询压力。
缓存预热
描述
缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统,避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。
缓存降级
描述
缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据。降级一般是有损的操作,所以尽量减少降级对于业务的影响程度。