Redis 缓存雪崩、缓存穿透、缓存击穿详解
缓存雪崩
缓存雪崩指的是大量缓存数据在同一时间失效,导致所有请求直接打到数据库或下游系统,造成数据库瞬时压力剧增,甚至可能引发系统崩溃。
形成原因:
- 缓存数据同时过期:由于缓存过期时间设置不合理,导致大量缓存同时失效,所有请求直接落到数据库。
- 缓存服务器宕机:缓存服务本身发生故障,无法响应请求,所有请求直接到数据库。
假设你有一个热门商品页面,所有缓存的商品数据过期时间相同,比如都设定为 12 小时。当 12 小时一到,所有缓存失效,用户请求打到数据库,数据库承受巨大压力,甚至可能导致崩溃。
缓存雪崩的避免方案
缓存过期时间设置随机化
为每个缓存的键设置不同的过期时间,避免大批量缓存同时失效。可以在原有过期时间的基础上,添加一个随机值(如 1-5 分钟的随机过期时间)。
缓存雪崩的解决方案
1. 限流降级
在发生缓存雪崩时,使用限流机制,限制进入数据库的请求数量。同时可以启用降级策略,例如返回默认数据或空数据来保证系统的可用性。
2. 缓存预热
在系统启动或缓存即将过期时,提前加载常用的数据到缓存中,避免缓存失效后瞬间打爆数据库。这种方式可以通过定时任务来实现。
缓存穿透
缓存穿透 指的是用户请求的数据根本不在缓存和数据库中,导致每次请求都直接查询数据库。即使我们把不存在的数据存入缓存,依然没有命中缓存,从而让缓存失效。
形成原因:
- 用户恶意请求一些不存在的数据,缓存中没有,数据库也查不到,每次查询都打到数据库,造成数据库负载过大。
如果用户不断请求数据库中不存在的 id
,比如负数 id=-1
或很大范围的 id
值,而系统没有处理此类非法请求,导致这些请求每次都穿过缓存直达数据库。
缓存穿透的解决方案
1. 使用布隆过滤器
布隆过滤器(Bloom Filter)是一种空间高效的概率性数据结构,可以快速判断某个数据是否存在。对于不存在的请求,在查询数据库之前先通过布隆过滤器检查是否有该记录,避免穿透到数据库。
2. 缓存空对象
对于查询结果为 null
的数据,直接缓存一个空值,并设置较短的过期时间(如 5 分钟),避免短时间内重复查询这些不存在的数据。
缓存击穿
缓存击穿 指的是某个热点数据在缓存失效的瞬间,有大量并发请求同时到达这个数据,由于缓存过期,这些请求直接打到数据库,导致数据库负载激增。
形成原因:
- 某些热门数据(热点 key)过期时间到达,但此时有大量并发请求请求这个数据,由于缓存失效,所有请求都会查询数据库,形成短时间内的高并发。
假设你有一个热门商品 id=100
的缓存,在缓存失效时(比如设定 5 分钟后过期),恰好有成千上万的用户访问这个商品。由于缓存失效,所有请求都会同时打到数据库,造成数据库压力激增。
缓存击穿的解决方案
1、缓存热点数据
对于热点数据,可以设置较长的过期时间,或者让这些数据不过期,定期主动更新缓存,避免过期时产生缓存击穿。
2、使用互斥锁(分布式锁)
在缓存失效的瞬间,为第一个请求的线程加锁,只有获取到锁的线程可以访问数据库并更新缓存,其他线程等待缓存更新后再读取缓存,避免数据库被并发请求打爆。