Redis 缓存设计:穿透、击穿、雪崩与最佳实践

Redis 缓存几乎是每个高并发系统的标配,但它不是”加上就快”的银弹。缓存用不好,反而会引发数据不一致甚至雪崩宕机。本文系统拆解缓存三大经典问题——穿透、击穿、雪崩,并给出可直接落地的解决方案。

一、缓存读取的标准流程

先建立统一认知:读请求优先查缓存,命中直接返回;未命中再查数据库,并把结果写回缓存。

def get_user(uid):
    data = redis.get(f"user:{uid}")
    if data is not None:
        return json.loads(data)        # 缓存命中
    row = db.query("SELECT * FROM user WHERE id=?", uid)
    if row:
        redis.setex(f"user:{uid}", 3600, json.dumps(row))  # 回填缓存
    return row

二、缓存穿透:查不存在的数据

现象:攻击者或 bug 持续请求一个数据库里根本没有的 ID,缓存永远不命中,请求全部打到 DB,把数据库压垮。

方案 1:缓存空值

查不到也写一个短过期(如 60s)的空标记,挡住重复查询:

    if not row:
        redis.setex(f"user:{uid}", 60, "NULL")  # 空值标记
        return None

方案 2:布隆过滤器(推荐)

在缓存前加一层布隆过滤器,所有合法 ID 提前放入。不存在的 ID 直接被拦截,连 Redis 都不用查:

# 使用 RedisBloom
BF.ADD user_filter 1001
BF.ADD user_filter 1002
BF.EXISTS user_filter 9999   # 返回 0 → 直接拒绝

三、缓存击穿:热点 key 过期瞬间

现象:某个超热 key(如首页爆款商品)突然过期,瞬间成千上万个请求同时击穿到数据库。

方案 1:互斥锁(Mutex)

只有一个线程去查 DB 并重建缓存,其余线程等待重试:

def get_with_lock(key):
    data = redis.get(key)
    if data:
        return data
    if redis.set(f"lock:{key}", 1, nx=True, ex=3):   # 抢到锁
        row = db.query(key)
        redis.setex(key, 3600, row)
        redis.delete(f"lock:{key}")
        return row
    time.sleep(0.05)
    return get_with_lock(key)   # 没抢到锁,稍后重试

方案 2:逻辑过期

不为 key 设物理 TTL,而在值里放过期时间戳;发现”已过期”时异步重建,期间返回旧值(容忍短暂旧数据)。适合只读一致性要求不极端的场景。

四、缓存雪崩:大量 key 同时失效

现象:批量 key 在同一时刻过期,或 Redis 宕机,请求全部落到数据库,瞬间打挂。

  • 过期时间加随机值expire = base + random(0, 300),避免集体失效。
  • 多级缓存:本地缓存(Caffeine)+ Redis,Redis 挂了还有本地兜底。
  • 高可用架构:Redis 主从 + 哨兵 / 集群,防止单点宕机。
  • 限流降级:DB 前加熔断,缓存全挂时返回默认页而非击穿数据库。

五、三大问题对比与选型

问题触发条件首选方案
穿透查不存在的数据布隆过滤器 + 空值缓存
击穿单个热点 key 过期互斥锁 / 逻辑过期
雪崩大量 key 同时失效随机过期 + 多级缓存 + 集群

六、Redis 内存与淘汰策略

缓存不是无限大。maxmemory-policy 决定内存满时怎么淘汰:

  • allkeys-lru:所有 key 里淘汰最久未用(最常用)。
  • volatile-lru:仅淘汰设了 TTL 的 key。
  • allkeys-lfu:按访问频率淘汰(Redis 4.0+)。
  • noeviction:不淘汰,写满报错(慎用)。

总结

缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略与高可用架构,Redis 才能真正成为系统的性能护城河。和数据库优化(如我们讲过的 PostgreSQL 慢查询调优)双管齐下,整体性能才会稳。

上一篇 GitHub Actions 实战:从零搭建 CI/CD 流水线
下一篇 2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖)