游乐游手机版
首页/AI热点日报/热点详情

最新丽水本地宝餐饮发票开具流程攻略

类型:热点整理2026-07-25
针对Redis缓存穿透、击穿、雪崩,需先清晰区分三者差异。穿透应结合参数校验、缓存空值及布隆过滤器处理;击穿用互斥锁(原子SETNXEX)或逻辑过期策略;雪崩通过随机TTL、热点预热、本地缓存及限流降级分层应对。面试重在结合项目实际设计。

最近浏览 Java 后端秋招提前批面经,发现 Redis 被问得非常频繁。不再是“Redis 有哪些数据结构”这类基础问题,而是直接切入项目场景:简历上写了缓存优化,那么缓存穿透、缓存击穿、缓存雪崩分别如何应对?为什么这样处理?线上是否真正实践过?

这道题看似是典型的八股文,但实际面试中很容易被深入追问。很多人一开始就机械背诵“穿透用布隆过滤器,击穿用互斥锁,雪崩加随机过期时间”,面试官多问几句就答不上来了。

更推荐按照“一次请求的完整流程”来回答。

首先明确三种缓存异常的区别

缓存穿透,指的是请求的数据在数据库中根本不存在。例如,有人持续查询 id 为负数的商品,缓存中不存在,数据库中也没有,每次请求都直接穿透缓存访问数据库,这才是真正的穿透。

缓存击穿,是指某个热点 key 突然失效。比如首页推荐配置、爆款商品库存、秒杀活动信息等,平时都由缓存承载压力,但某时刻 key 过期,大量并发请求瞬间涌向数据库。

缓存雪崩,是指大量 key 在同一时间段集中过期,或者 Redis 集群本身发生短暂不可用。这不是单个热点 key 的问题,而是缓存层整体失效。

面试中先清晰区分这三个概念,后续讨论才能深入。否则将击穿误认为是穿透,面试官会默认你只是死记硬背。

缓存穿透:不要只提布隆过滤器

应对缓存穿透的第一层防线其实是参数校验。

如果业务规定商品 id 必须是正整数,那么负数、超长字符串、明显不合法的枚举值等,都应在入口处拦截。不要让这类请求到达缓存层,更不能进入数据库。

第二层处理是缓存空值。当数据库查询结果为空时,可以将空结果也写入缓存,并设置较短的过期时间,例如几十秒到几分钟。这样相同的无效 key 就不会反复查询数据库。

布隆过滤器适用于更复杂的场景:数据集合相对稳定、非法 key 数量庞大、数据库压力已明显增大。其特点是可能误判某个 key“存在”,但绝不会将真实存在的 key 误判为不存在。因此,它可以作为前置过滤手段,但不能完全依赖它作为最终判断依据。

一个比较稳妥的回答可以这样组织:

  • 首先进行入参校验,拦截明显非法的请求;
  • 当数据库查询为空时,缓存空值,防止相同的无效 key 反复穿透数据库;
  • 如果非法 key 数量很大,再将合法 id 集合构建到布隆过滤器中,作为前置判断。

如果面试官进一步追问“缓存空值是否会污染 Redis”,可以回答:空值的 TTL 要设置得短,value 要小,并且只针对高频不存在的 key 进行缓存,而不是对所有未命中数据都盲目写入。

缓存击穿:互斥锁不仅仅是 SETNX

当热点 key 过期时,最糟糕的情况是大量线程同时查询数据库并尝试回写缓存。

常见解决方案是使用互斥锁:只有获取到锁的线程才能查询数据库并重建缓存,其他线程则等待后重试,或者直接返回旧数据。

这里有一个常见陷阱:不要使用“SETNX 后再 EXPIRE”的组合。这两个命令不是原子操作,如果在中间进程崩溃,可能导致死锁。Redis 中更推荐使用一条 SET 命令,同时带上 NX 和 EX 参数,将“仅在不存在时设置”和“过期时间”合并为一个原子操作。解锁时还需要校验 value,通常使用 Lua 脚本确保只删除自己持有的锁。

如果业务允许短暂返回旧数据,逻辑过期方案会更加优雅:缓存中不仅存储数据,还附带一个逻辑过期时间。当请求发现逻辑过期时,不会立即让所有线程去查询数据库,而是由单个线程异步刷新缓存,其他线程则继续使用旧数据。

这种方案在首页配置、排行榜、推荐位等场景中非常常见。用户看到几十秒前的数据通常影响不大,但数据库被击穿则是真实的事故。

可以这样回答:

  • 对于强一致性要求高的热点 key,采用互斥锁重建缓存;
  • 对于读多写少、允许短暂旧值的场景,使用逻辑过期加异步刷新;
  • 锁必须设置过期时间,value 要保证唯一性,删除锁时需校验 owner。

这样的回答比单纯背诵“互斥锁”更有深度。

缓存雪崩:随机 TTL 只是最基础的措施

缓存雪崩的典型原因主要有两个。

第一类是大量 key 同时过期。例如批量导入缓存时,全部设置成 30 分钟,半小时后同时失效。这种情况可以通过随机 TTL 缓解:在基础过期时间上增加随机抖动,使 key 的失效时间分散开。

第二类是缓存服务本身不可用。这已经不是随机 TTL 能应对的了,需要评估系统是否具备本地缓存、限流、降级、熔断等机制,以及核心数据能否提前预热。

面试时可以从以下层次回答:

  • 过期时间层:为 TTL 增加随机值,避免同一批 key 同时失效。
  • 热点数据层:在上线或活动开始前进行数据预热,避免等待用户请求触发重建。
  • 系统保护层:使用本地缓存作为兜底、实施接口限流、保护数据库、对非核心功能进行降级。

如果项目只是普通后台系统,没有高并发活动,不必强行编造秒杀场景。可以如实说“没有做过秒杀,但在后台字典、配置缓存中会使用随机 TTL,避免定时任务批量刷新导致同时过期”。这样的回答反而更真实可信。

面试官真正想听的,不是技术名词

这个问题最终往往会落到项目实际经验上。

如果简历中写了 Redis 经验,建议提前想清楚以下几个问题:

  • 哪些数据使用了缓存?为什么这些数据适合放入缓存?
  • key 是如何设计的?是否包含前缀、版本号、业务 id?
  • TTL 设置多长时间?是固定值还是带有随机偏移?
  • 数据更新时,采用删除缓存、更新缓存,还是延迟双删策略?
  • 如果缓存未命中,数据库能否承受压力?是否有限流措施?

这比背诵十页 Redis 面试题更重要。

来源:https://segmentfault.com/a/1190000048073427

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。