前言

缓存和高并发是企业系统里最常见的组合题。面试通常会问:

  • 为什么要用缓存。
  • 缓存和数据库怎么保持一致。
  • 热点 Key 怎么处理。
  • 缓存穿透、击穿、雪崩分别是什么。
  • 本地缓存和 Redis 怎么组合。
  • 高并发下怎么防止把数据库打挂。

这些题的核心是:缓存不是单纯“提速”,而是系统抗压、隔离、削峰和保护数据库的一层架构。

为什么需要缓存

缓存通常解决四类问题:

  1. 降低数据库压力。
  2. 提升热点读性能。
  3. 抗流量峰值。
  4. 支撑更低的响应时间。
flowchart LR
    A[用户请求] --> B{缓存命中?}
    B -->|是| C[直接返回]
    B -->|否| D[访问数据库]
    D --> E[回填缓存]
    E --> C

常见业务:

  • 首页配置。
  • 商品详情。
  • 用户基础信息。
  • 价格和库存快照。
  • 活动配置。

缓存架构怎么选

方案一:只用 Redis

优点:

  • 统一缓存中心。
  • 多实例共享。
  • 适合分布式系统。

缺点:

  • 网络开销比本地缓存大。
  • 受 Redis 单点或集群状态影响。

适合:

  • 中高并发业务。
  • 多实例部署。

方案二:本地缓存 + Redis

优点:

  • 本地命中最快。
  • Redis 作为二级缓存。

缺点:

  • 一致性更复杂。
  • 多实例缓存可能不一致。

适合:

  • 读多写少。
  • 热点配置、字典项、短周期数据。

方案三:多级缓存

本地缓存 + Redis + 数据库。

优点:

  • 性能强。
  • 对数据库保护更好。

缺点:

  • 运维和失效策略复杂。

适合:

  • 大型电商、内容系统、配置中心。

热点数据怎么处理

热点 Key 是最常见的线上问题之一。

典型场景:

  • 秒杀商品。
  • 首页爆款商品。
  • 某个热门活动配置。

常见处理:

  1. 本地缓存短 TTL。
  2. Redis 分片或复制扩展读能力。
  3. 热点 Key 拆分。
  4. 预热。
  5. 限流。
  6. 旁路降级。
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 访问压力。

缓存能解决所有高并发问题吗?

不能。它只能缓解读压力,写压力、下游依赖、锁竞争、消息积压、数据库热点都还要单独治理。

总结

缓存高并发的回答可以围绕这五件事:

  1. 为什么用缓存:提速、抗压、保护数据库。
  2. 怎么分层:本地缓存、Redis、多级缓存。
  3. 怎么一致:更新后删缓存、延迟双删、消息补偿。
  4. 怎么抗异常:穿透、击穿、雪崩、大 Key、热点 Key。
  5. 怎么取舍:读写比例、一致性要求、运维复杂度。

真正落地的缓存设计,不是“把数据塞进 Redis”,而是构建一层可控、可回源、可降级的抗压体系。