在高并发系统中,缓存(如 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. 压测验证:上线前进行高并发压测,验证缓存策略有效性,及时调整。

 

缓存是性能优化的利器,但也是一把双刃剑。理解并妥善处理缓存击穿、穿透、雪崩这三大问题,是我们在开发中构建高可用、高性能系统的关键一步。

 

Logo

惟楚有才,于斯为盛。欢迎来到长沙!!! 茶颜悦色、臭豆腐、CSDN和你一个都不能少~

更多推荐