Redis 缓存雪崩的三个真实场景与应对

举报
yd_248372697 发表于 2026/11/13 11:23:37 2026/11/13
【摘要】 三个真实场景与对应的兜底策略。

Redis 缓存雪崩的三个真实场景与应对

先明确一件事

缓存雪崩不是"缓存挂了"这么简单。真正让服务崩掉的,是大量请求在缓存同时失效的瞬间全部打到数据库,数据库连接池被打满,超过恢复阈值之后即使缓存回来也救不动。这篇记录我在生产上遇到的三种情况,以及各自的处理方式。

场景一:整点批量预热,key 同时过期

运营活动在 0 点刷新榜单,几千个 key 的 TTL 都设成 24 小时,第二天 0 点整批失效。

处理方式很简单,把 TTL 打散:

import random
ttl = 24 * 3600 + random.randint(-1800, 1800)
redis.setex(key, ttl, value)

同一个 key 的过期时间落在半小时的窗口里,数据库压力被摊平,峰值下降约 70%。

场景二:热点 key 过期瞬间的击穿

单个热点 key 过期,几千 QPS 同时回源。这时候加互斥锁比打散 TTL 更有效:

def get_with_mutex(key):
    val = redis.get(key)
    if val is not None:
        return val
    if redis.set(f"lock:{key}", "1", nx=True, ex=3):
        try:
            val = load_from_db(key)
            redis.setex(key, 600, val)
            return val
        finally:
            redis.delete(f"lock:{key}")
    for _ in range(50):
        time.sleep(0.02)
        val = redis.get(key)
        if val is not None:
            return val
    return load_from_db(key)

注意最后那个兜底:锁等待超时后仍然回源,宁可多打一点数据库,也不要让请求卡死。

场景三:Redis 主从切换期间全量回源

这是最容易被忽略的。主库宕机,哨兵切换需要十几秒,这期间所有读请求 miss,直接压垮数据库。

两个手段:

• 本地进程内加一层很短的缓存(例如 200ms 的 LRU),能挡掉大部分重复读

• 降级开关:检测到 Redis 不可用时,读接口直接返回默认值或旧数据,不让流量穿透

监控指标

不要只盯 Redis 的命中率,真正有意义的是这几个:

• 数据库 QPS 的突增比例(超过基线 3 倍就告警)

• 应用侧连接池等待时间 P99

• 回源请求数 / 总请求数

小结

雪崩的根因永远是"瞬时并发 × 无缓存",所以解法也就三条:摊平时间、串行化回源、加一层更近的缓存。工程上最有效的往往不是最复杂的方案,而是把 TTL 加个随机数这么小的事。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。