Java面试要点:热点数据、缓存一致性与抗压设计
前言
缓存和高并发是企业系统里最常见的组合题。面试通常会问:
- 为什么要用缓存。
- 缓存和数据库怎么保持一致。
- 热点 Key 怎么处理。
- 缓存穿透、击穿、雪崩分别是什么。
- 本地缓存和 Redis 怎么组合。
- 高并发下怎么防止把数据库打挂。
这些题的核心是:缓存不是单纯“提速”,而是系统抗压、隔离、削峰和保护数据库的一层架构。
为什么需要缓存
缓存通常解决四类问题:
- 降低数据库压力。
- 提升热点读性能。
- 抗流量峰值。
- 支撑更低的响应时间。
flowchart LR
A[用户请求] --> B{缓存命中?}
B -->|是| C[直接返回]
B -->|否| D[访问数据库]
D --> E[回填缓存]
E --> C
常见业务:
- 首页配置。
- 商品详情。
- 用户基础信息。
- 价格和库存快照。
- 活动配置。
缓存架构怎么选
方案一:只用 Redis
优点:
- 统一缓存中心。
- 多实例共享。
- 适合分布式系统。
缺点:
- 网络开销比本地缓存大。
- 受 Redis 单点或集群状态影响。
适合:
- 中高并发业务。
- 多实例部署。
方案二:本地缓存 + Redis
优点:
- 本地命中最快。
- Redis 作为二级缓存。
缺点:
- 一致性更复杂。
- 多实例缓存可能不一致。
适合:
- 读多写少。
- 热点配置、字典项、短周期数据。
方案三:多级缓存
本地缓存 + Redis + 数据库。
优点:
- 性能强。
- 对数据库保护更好。
缺点:
- 运维和失效策略复杂。
适合:
- 大型电商、内容系统、配置中心。
热点数据怎么处理
热点 Key 是最常见的线上问题之一。
典型场景:
- 秒杀商品。
- 首页爆款商品。
- 某个热门活动配置。
常见处理:
- 本地缓存短 TTL。
- Redis 分片或复制扩展读能力。
- 热点 Key 拆分。
- 预热。
- 限流。
- 旁路降级。
flowchart TD
A[热点 Key] --> B{是否超高频}
B -->|否| C[普通 Redis 缓存]
B -->|是| D[本地缓存 + Redis]
D --> E[预热 + 限流 + 降级]
缓存一致性怎么做
缓存一致性通常有三种思路:
方案一:先更新数据库,再删缓存
这是最常见的缓存一致性策略。
优点:
- 简单。
- 适合读多写少。
缺点:
- 存在短暂脏读窗口。
- 并发下可能出现回填旧值。
方案二:先删缓存,再更新数据库
优点:
- 读请求更容易回源数据库。
缺点:
- 并发复杂。
- 可能出现空窗期和旧值回填。
方案三:延迟双删
更新数据库后删一次缓存,稍后再删一次。
适合:
- 对一致性要求高但不能上分布式事务的场景。
缺点:
- 不是严格一致,只是减小不一致窗口。
sequenceDiagram
participant W as 写请求
participant DB as 数据库
participant C as 缓存
W->>DB: 更新数据
W->>C: 删除缓存
W-->>W: 延迟一段时间
W->>C: 再次删除缓存
面试表达:
缓存一致性没有银弹。大多数业务会选择“更新数据库后删除缓存”,再配合延迟双删、消息通知或最终一致任务来减少脏读窗口。
缓存穿透、击穿、雪崩
穿透
请求的 key 在缓存和数据库里都不存在。
治理:
- 缓存空值。
- 布隆过滤器。
- 参数校验。
击穿
某个热点 key 过期,瞬间大量请求打到数据库。
治理:
- 互斥锁。
- 逻辑过期。
- 热点预热。
雪崩
大量 key 在同一时间过期,导致缓存层集体失效。
治理:
- 随机 TTL。
- 多级缓存。
- 限流降级。
- 分批预热。
| 问题 | 本质 | 典型治理 |
|---|---|---|
| 穿透 | 查不存在的数据 | 空值、布隆过滤器 |
| 击穿 | 热点 Key 瞬时失效 | 互斥锁、逻辑过期 |
| 雪崩 | 大量 Key 同时失效 | 随机 TTL、限流、降级 |
大 Key 怎么处理
大 Key 会带来这些问题:
- 网络传输慢。
- 序列化和反序列化慢。
- 复制和持久化压力大。
- 删除或查询时阻塞。
常见优化:
- 拆分大对象。
- 用 Hash 分字段而不是一个超大 JSON。
- 分页加载。
- 控制集合大小。
读写放大怎么理解
高并发缓存不是只看命中率,还要看读写放大:
- 写多会导致缓存频繁失效或更新。
- 多级缓存会带来更多一致性成本。
- 大 key 读写会放大网络和序列化开销。
面试时要讲清楚:
不是所有数据都值得进缓存。缓存适合读多写少、访问热点明显、允许最终一致的场景。
多方案对比
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 热点配置 | 本地缓存 + Redis | 命中快、更新频率低 |
| 商品详情 | Redis + 数据库 | 读多写少,易回源 |
| 秒杀库存 | Redis 预扣 + MQ | 高并发抗压 |
| 用户会话 | Redis | 分布式共享方便 |
| 首页推荐 | 多级缓存 | 降低数据库和搜索压力 |
高频面试题
为什么缓存不能代替数据库?
缓存本质上是临时加速层,不是最终数据源。它可能失效、被淘汰、重启丢失,所以最终数据必须落库。
为什么说缓存一致性没有绝对完美方案?
因为数据库和缓存不是一个原子事务系统。你只能在一致性、性能和复杂度之间做取舍。
本地缓存和 Redis 怎么选?
本地缓存更快,但只适合单机或局部热点;Redis 适合共享缓存和分布式场景。企业里常组合使用。
热点 Key 为什么危险?
因为所有请求集中打到同一个 Key,容易放大数据库回源和 Redis 访问压力。
缓存能解决所有高并发问题吗?
不能。它只能缓解读压力,写压力、下游依赖、锁竞争、消息积压、数据库热点都还要单独治理。
总结
缓存高并发的回答可以围绕这五件事:
- 为什么用缓存:提速、抗压、保护数据库。
- 怎么分层:本地缓存、Redis、多级缓存。
- 怎么一致:更新后删缓存、延迟双删、消息补偿。
- 怎么抗异常:穿透、击穿、雪崩、大 Key、热点 Key。
- 怎么取舍:读写比例、一致性要求、运维复杂度。
真正落地的缓存设计,不是“把数据塞进 Redis”,而是构建一层可控、可回源、可降级的抗压体系。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Junly博客!
评论


