缓存三大经典问题详解:缓存击穿、缓存穿透、缓存雪崩
缓存击穿是指某个热点数据在缓存中过期后,大量并发请求同时访问该数据,大家都同时访问数据库,导致这些请求全部打到数据库上,造成数据库瞬时压力剧增。缓存穿透是指查询一个不存在的数据,由于数据库中没有,缓存又没有存储,导致每次请求都绕过缓存,直接访问数据库。缓存雪崩是指大量缓存数据在同一时间过期,或Redis 服务宕机,导致所有请求都打到数据库,造成数据库崩溃。
在高并发系统中,缓存(如 Redis)是我们提升系统性能、降低数据库压力的重要手段。然而,缓存的使用也带来了几个经典问题:缓存击穿、缓存穿透、缓存雪崩。如果我们在开发中不加以处理,这些问题可能导致数据库压力骤增,甚至系统崩溃。接下来给大家分别介绍这三个概念,并给出常见的解决方案和代码样例。
一、缓存击穿(Cache Breakdown)
1. 什么是缓存击穿?
缓存击穿是指某个热点数据在缓存中过期后,大量并发请求同时访问数据库查询该数据,导致这些请求全部打到数据库上,造成数据库瞬时压力剧增。
2. 成因
- 热点数据(如热门商品、首页信息)缓存设置了过期时间,但缓存已经过期了。
- 然而当缓存过期的瞬间,多个线程/请求同时发现缓存中没有数据。
- 所有请求都去查询数据库,形成“并发洪峰”,大量请求打到数据库。
3. 危害
- 数据库瞬间承受大量读请求,可能造成响应变慢甚至宕机。
- 系统整体性能下降,用户体验变差。
4. 解决方案
方案一:互斥锁(Mutex Lock)(推荐)
在缓存失效时,我们不应该让所有请求都去查数据库,而是只让一个线程去重建缓存,其他线程等待并重试缓存,重试3次左右还没有则直接返回业务要求的数据。
⚠️ 注意:实际开发时,建议使用 Redis 的 SET key value NX PX 命令,或更成熟可靠的Redisson(推荐)实现更可靠的分布式锁。
方案二:永不过期 or 逻辑过期
对热点数据不设置expires物理过期时间,而是通过后台线程异步更新缓存,或设置“逻辑过期时间”字段,此时就不会存在没有缓存的问题。这对于不要求高实时性的数据是个很不错的实现方法。
二、缓存穿透(Cache Penetration)
1. 什么是缓存穿透?
缓存穿透是指查询一个不存在的数据,由于数据库中没有,缓存又没有存储,导致每次请求都绕过缓存,直接访问数据库。
2. 成因
- 用户恶意攻击(如遍历 ID)。
- 业务逻辑错误导致查询无效数据。
3. 危害
- 每次请求都穿透到数据库,导致数据库压力大。
- 可能被用于 DoS 攻击,造成系统的崩溃。
4. 解决方案
方案一:缓存空值(Null Value Caching)
即使数据库查不到数据,我们也应该将空结果缓存一段时间,避免重复查询数据库。
⚠️注意:空值缓存时间不要设置过长,防止缓存穿透的同时,要避免数据长时间“假存在”。
方案二:布隆过滤器(Bloom Filter)(推荐)
在访问缓存前,先通过布隆过滤器判断数据是否可能存在。如果布隆过滤器说“不存在”,则直接返回,不查缓存和数据库。
- 优点:空间效率高,适合大量数据的场景。
- 缺点:存在误判的可能(即把存在判断为不存在),需人工定期重建。
在开发中推荐两个方案同时使用,方案一可以很好地弥补布隆过滤器存在的误判问题,二者结合更加可靠。
三、缓存雪崩(Cache Avalanche)
1. 什么是缓存雪崩?
缓存雪崩是指大量缓存数据在同一时间过期,或Redis 服务宕机,导致所有请求都打到数据库,造成数据库崩溃。
2. 成因
- 缓存集中过期(如大量缓存统一设置 2 小时过期),导致大量线程访问数据库。
- Redis 集群故障或网络问题,导致Redis缓存不可用。
3. 危害
- 数据库瞬间承受全部流量,极可能宕机。
- 系统整体不可用。
4. 解决方案
方案一:设置随机过期时间
避免大量缓存同时过期,给过期时间添加随机值。
⚠️注意:一般开发中会在原有过期时间基础上浮动10%-20%
方案二:多级缓存(Local + Redis)
使用本地缓存(如 Caffeine、Ehcache)作为第一层,Redis 作为第二层,降低对 Redis 的依赖。
方案三:高可用架构
Redis 集群部署(主从 + 哨兵 或 Redis Cluster)。保证 Redis 的高可用性,主节点负责写,从节点负责读,主从分离,避免单点故障而系统崩溃。
方案四:服务降级与熔断
当 Redis 不可用时,我们还可以启用降级策略(如返回默认值、静态页面),结合 Hystrix 或 Sentinel 实现熔断。
四、开发中的最佳实践建议
1. 合理设置过期时间:避免统一过期,加入随机因子。
2. 热点数据特殊处理:如首页、爆款商品,使用永不过期 + 异步更新。
3. 监控与告警:监控缓存命中率、Redis 负载、数据库 QPS。
4. 压测验证:上线前进行高并发压测,验证缓存策略有效性,及时调整。
缓存是性能优化的利器,但也是一把双刃剑。理解并妥善处理缓存击穿、穿透、雪崩这三大问题,是我们在开发中构建高可用、高性能系统的关键一步。
更多推荐
所有评论(0)