视频加载失败

Redis 缓存设计:穿透、击穿、雪崩与实战

475 字
2 分钟
Redis 缓存设计:穿透、击穿、雪崩与实战

缓存的基本读写#

最常见的「Cache Aside」模式:

  1. 读:先查缓存,命中直接返回;未命中查库,写入缓存。
  2. 写:先更新数据库,再删除缓存(而非更新缓存)。
读: cache.get(k) → 命中返回; 未命中 db.query → cache.set(k, v, ttl)
写: db.update → cache.del(k)

缓存穿透:查根本不存在的数据#

成因:请求的参数在数据库中不存在(如 id = -1),缓存和数据库都查不到,恶意流量直接打到 DB。

解法一:缓存空值

v = cache.get(k)
if v == nil:
v = db.query(k)
if v == nil:
cache.set(k, NULL, 60s) # 缓存短时间空标记
return v

解法二:布隆过滤器——在缓存前加一层 BloomFilter,不存在的 key 直接拒绝。

if !bloom.mightContain(k): return nil # 一定不存在

缓存击穿:热点 key 突然失效#

成因:某个超热点 key(如首页配置)过期瞬间,海量请求同时穿透到 DB。

解法:互斥锁(singleflight)

v = cache.get(k)
if v == nil:
if lock.tryAcquire(k): # 只有一个线程回源
v = db.query(k)
cache.set(k, v, ttl)
lock.release(k)
else:
sleep(50ms); retry() # 其余线程等待并重试

另一种思路是逻辑过期:value 里带过期时间戳,异步刷新,读时不阻塞。

缓存雪崩:大量 key 同时失效#

成因:批量 key 设置了相同 TTL,同一时刻集体失效,DB 瞬间被打垮。

解法:随机过期时间

ttl = base + random(0, jitter) # 例如 3600 ± 600 秒
cache.set(k, v, ttl)

配合多级缓存(本地 Caffeine + Redis)与限流降级,可进一步兜底。

最佳实践小结#

  • 给所有 key 设 TTL,避免无限堆积;
  • 写操作删缓存而非更新缓存;
  • 大 value 拆分,避免热 key 集中;
  • 监控命中率,命中率低于 90% 要警惕。

缓存的本质是用空间换时间,代价是一致性。明确业务能接受的最终一致窗口,再决定策略。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Redis 缓存设计:穿透、击穿、雪崩与实战
https://www.devng.cn/posts/redis-cache-design/
作者
CyreneStar
发布于
2026-08-08
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
CyreneStar
全栈开发者 / DevOps 实践者。路漫漫其修远兮,吾将上下而求索。
公告
欢迎来到 CyreneStar 的博客,记录技术探索与工程实践。
分类
标签
站点统计
文章
4
分类
4
标签
14
总字数
1,402
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录