
这篇文章把 Redis 缓存穿透、击穿、雪崩拆成可判断的故障范围,并给出回源控制、TTL 设计、监控验证和面试话术清单。
缓存穿透是缓存和数据库里都没有这个数据,请求反复查库;缓存击穿是某个热点 key 失效后,大量并发请求同时回源;缓存雪崩是大量 key 集中过期,或者缓存整体不可用,导致大批请求回源。我的处理顺序是:先做参数校验和空值保护,再针对热点 key 做互斥加载或逻辑过期,对批量过期做 TTL 抖动、预热、限流和降级。最后用缓存命中率、回源 QPS、数据库连接池和接口延迟验证方案是否真的生效。
| 问题 | 数据状态 | 典型范围 | 面试时先说什么 |
|---|---|---|---|
| 缓存穿透 | 缓存没有,数据库也没有 | 大量不存在或非法 key | 先拦参数、缓存空值,必要时用布隆过滤器 |
| 缓存击穿 | 数据库有,但热点 key 在缓存中失效 | 一个或少数热点 key | 让同一个 key 同时只有一个请求回源 |
| 缓存雪崩 | 大量 key 同时失效,或缓存整体不可用 | 一批 key,甚至整个缓存层 | 错开过期时间,并限制回源流量 |
如果是明显非法参数,我会在接口层拦截;如果是合法但不存在的数据,我会缓存短 TTL 的空值,避免同一个不存在的 key 持续查库。布隆过滤器是否引入,要看 key 集合是否稳定、更新链路是否可靠,以及误判带来的回源成本。
EXPIRE 会给 key 设置过期时间,超时后自动删除;TTL 可以查看剩余生存时间。4 所以,TTL 不是随手填一个固定数字就结束了。批量生成缓存时,可以在基础 TTL 上加入受控的随机抖动,让 key 不要在同一秒集中失效;热点数据还可以在高峰前预热,或者采用后台刷新与可接受的短暂旧值。锁粒度按 key 控制,避免不同商品相互阻塞。持锁请求负责一次回源和回填,锁必须有超时,避免异常退出后永久占用。未拿到锁的请求只做有限次数重试,超过预算就走降级。流量很小或只有单实例时,我不会为了背概念强行引入分布式锁。
INFO 的 stats 部分提供 keyspace_hits 和 keyspace_misses,分别表示 key 查找成功和失败的次数,可以据此观察命中与未命中趋势。5 面试中可以按这张清单回答:| 观察项 | 你要确认的问题 |
|---|---|
| 缓存命中率 | 失效后是否出现异常下降,是否只集中在某个业务 key 前缀 |
| 回源 QPS | miss 增加后,数据库查询是否同步放大 |
| 热点 key 分布 | 是单个 key 的访问集中,还是大量 key 一起过期 |
| 锁等待与回源耗时 | 是否只有一个请求查库,等待请求是否超出接口预算 |
| 数据库连接池、CPU、P95/P99 | 保护措施有没有把压力转移成排队和长尾 |
SLOWLOG 会记录超过配置执行时间阈值的命令,但它不包含与客户端通信的网络 I/O 时间,所以不能只看慢日志就判断端到端延迟。6我会先按 key 前缀和时间窗口看命中率、miss 数和回源 QPS,再对照数据库连接池和接口 P99。如果只有一个热点 key 的 miss 突增,我优先查互斥加载和热点访问;如果多个前缀同时下降,我会查批量任务、TTL 分布和缓存实例健康。Redis 慢日志只能说明命令执行阶段,网络和应用排队要看链路指标。
在[业务接口]中,我们发现[具体时间窗口内的异常信号]。我先按 key 维度看缓存 miss 和回源 QPS,判断这是[一个热点 key / 多个 key 集中过期 / 大量不存在 key]。随后采用[具体措施],把回源并发控制在[真实约束],并通过[真实监控指标]验证。这个方案的代价是[旧值可能短暂不新鲜 / 增加了锁等待 / 需要维护过滤器],所以只用于[明确业务范围]。
docs.aws.amazon.com
cloud.tencent.com
redis.io
redis.io
redis.io
This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.