Redis 缓存设计:穿透、击穿、雪崩与实战
475 字
2 分钟
Redis 缓存设计:穿透、击穿、雪崩与实战
缓存的基本读写
最常见的「Cache Aside」模式:
- 读:先查缓存,命中直接返回;未命中查库,写入缓存。
- 写:先更新数据库,再删除缓存(而非更新缓存)。
读: 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/相关文章智能推荐
1
Git 提交规范与 Conventional Commits 实践
研发协作为什么需要提交规范、Conventional Commits 规范详解、如何配合 git hooks 与工具自动校验,以及语义化版本号如何从中推导。
2
用 GitHub Actions 搭建轻量 CI/CD 流水线
DevOps从零配置 GitHub Actions,实现代码推送自动 lint、测试、构建与部署,覆盖 workflow 语法、缓存加速、密钥管理与多环境发布。
3
TypeScript 泛型与类型体操入门
前端从泛型基础到 Utility Types 与条件类型,循序渐进掌握 TypeScript 类型层面的抽象能力,写出更安全的代码。
随机文章随机推荐












