【Redis】缓存穿透、缓存击穿、缓存雪崩
在分布式系统和高并发场景中,缓存机制是提高系统性能的重要手段。
然而,缓存在某些情况下会出现三种典型的异常现象:缓存穿透、缓存击穿和缓存雪崩。
1. 缓存穿透
现象
查询的数据在缓存和数据库中都不存在,每次请求都直接打到数据库,导致数据库压力陡增。
原因
- 恶意攻击或爬虫发送大量无效请求。
- 缓存层未对空值或错误结果进行缓存。
解决方案
- 缓存空值:即使数据库返回空值,也写入缓存并设置短暂过期时间。
if result == nil { redis.Set("key", "null", 60*time.Second) }
- 布隆过滤器:提前判断 Key 是否存在。
- 接口限流和黑名单。
2. 缓存击穿
现象
热点数据(访问量极高的数据)在缓存过期瞬间,大量请求同时打到数据库,导致数据库崩溃。
原因
- 缓存失效导致瞬时请求全部涌向数据库。
- 高并发环境下缺乏对缓存重建的控制。
解决方案
- 设置热点数据永不过期,只通过手动更新缓存。
- 加互斥锁:只允许一个线程更新缓存,其他线程等待。
lockKey := "lock_key" if !redis.SetNX(lockKey, 1, 10*time.Second).Val() { time.Sleep(50 * time.Millisecond) }
- 提前缓存预热:在缓存即将过期时,提前触发缓存更新。
3. 缓存雪崩
现象
大量缓存同时失效,导致瞬时请求全部打到数据库,数据库压力暴增。
原因
- 缓存数据集中设置了相同的过期时间。
- Redis 宕机或网络故障导致缓存不可用。
解决方案
- 设置过期时间随机化:避免缓存同时失效。
expireTime := 60 + rand.Intn(30) // 随机增加30秒 redis.Set("key", value, time.Duration(expireTime)*time.Second)
- 多级缓存架构:使用本地缓存(如 Guava Cache)+ 分布式缓存(Redis)。
- Redis 集群部署,避免单点故障。
总结
异常类型 | 触发场景 | 解决方案 |
---|---|---|
缓存穿透 | 请求的数据不存在 | 缓存空值、布隆过滤器 |
缓存击穿 | 热点数据过期的瞬间 | 加锁、缓存预热 |
缓存雪崩 | 大量缓存同时失效 | 过期时间随机化、多级缓存 |
https://github.com/0voice