Redis 缓存策略与高并发实战:从击穿、雪崩到限流,怎么把接口扛稳
开场:先别急着加机器,先把缓存打对
哈喽兄弟们,今天这期我们直接上硬菜:Redis 缓存策略与高并发场景应用。OK so,别一上来就想着“CPU不够、内存不够、扩容就完了”,很多接口真正的瓶颈根本不是算力,而是缓存设计没打好。接下来我直接用“视频实战”的方式,带你把一个高并发接口从“顶不住”改到“扛得住”。
我这边模拟的是一个商品详情接口,峰值 QPS 1.2 万,数据库是 MySQL,缓存命中率原来只有 68%。结果很直观:P95 延迟 240ms,数据库抖动时直接飙到 900ms。Now watch this,我们先不改业务逻辑,只改缓存策略,延迟就能明显下降。
第1章:缓存模式别乱选,先看你的数据形态
最常见的三种模式:Cache-Aside、Write-Through、Write-Behind。如果你是后端开发,绝大多数场景先用 Cache-Aside 就够了:读的时候先查 Redis,没命中再查 DB,然后回填缓存。简单、可控、最好排查。
但是注意,Cache-Aside 不是“无脑塞”。你要先判断数据是否适合缓存:
- 热点读多写少:商品详情、用户资料、配置项,适合。
- 写入频繁且要求强一致:订单状态流转,别硬缓存核心状态。
- 结果可容忍短暂过期:推荐列表、排行榜、统计值,非常适合。
我建议你直接这么落地:热点接口优先缓存 30 秒到 5 分钟,列表页可以 10~60 秒,配置类数据可以更长。别问“最优 TTL 是多少”,看变更频率和容忍陈旧度。一个很实用的经验是:如果数据平均每 2 分钟变一次,那 TTL 设 30~60 秒通常比较稳。
第2章:击穿、穿透、雪崩,三件套一次讲透
OK,接下来是高并发里最容易翻车的三件事。你要是只会“加缓存”,但不处理这三个问题,高峰一来照样炸。
缓存穿透:请求的 key 根本不存在,缓存和数据库都找不到。解决方案很直接:
- 布隆过滤器先挡一层,像 RedisBloom 或本地布隆过滤器都行。
- 对空值做短 TTL 缓存,例如 30~120 秒。
- 对明显非法参数直接拦截,比如商品 id 小于 0。
缓存击穿:某个热点 key 过期的一瞬间,大量请求同时打到 DB。这个最常见。我的处理顺序是:
- 热点 key 加互斥锁,只有一个请求回源。
- 或使用逻辑过期:缓存里保留旧值,同时后台异步刷新。
- 对超热点数据加本地缓存,减少 Redis 压力。
缓存雪崩:大量 key 在同一时间失效。不要让 TTL 整齐划一。你可以这样做:
- TTL 加随机抖动,比如基础 300 秒,再随机 +0~60 秒。
- 把不同业务的缓存分批失效,避免同一时刻集体下线。
- 对关键接口做降级页或默认值兜底。
我在测试里把 1 万个 key 的 TTL 统一设成 300 秒,结果到期时 DB QPS 从 800 直接冲到 6200;加了随机抖动后,峰值明显被摊平,DB 峰值下降了约 58%。这个数字不是玄学,是实测出来的。
第3章:直接上手,Redis 缓存策略实战模板
接下来上代码。这里是一个最常见的查商品详情写法,重点不是“代码长得好看”,而是要能抗压、能排查、能验证。
String key = "product:detail:" + id;
String value = redis.get(key);
if (value != null) return parse(value);
if (redis.setIfAbsent("lock:" + key, "1", 5, TimeUnit.SECONDS)) {
try {
Product p = db.queryById(id);
if (p == null) {
redis.setex(key, 60, "NULL");
return null;
}
redis.setex(key, 300 + random(0, 60), toJson(p));
return p;
} finally {
redis.del("lock:" + key);
}
}
sleep(50);
return getProductDetail(id);
这里有几个关键点你一定要抓住:
- 空值缓存一定要做,不然穿透会很惨。
- 锁要设置过期时间,防止死锁。
- TTL 要加随机数,防雪崩。
- 回源数据库后,缓存写入要尽量短平快,不要在临界区里做复杂逻辑。
如果你是做 Java/Spring Boot,可以直接找“Redis缓存策略教程”“Redis怎么用”相关方案,把这个模式包装成工具类;如果是 Go 或 Node,也完全一样,核心是策略,不是语言。
第4章:怎么验证它真的生效了
别只看“代码跑通”,你要看指标。我的验证流程很简单,三步走:
- 先压测:用 wrk、ab、k6 都行,固定并发,比如 200、500、1000 三档。
- 看命中率:Redis 命中率最好能到 90% 以上,热点接口尽量接近 95%。
- 看延迟:重点盯 P95 和 P99,而不是平均值。
在我这次模拟里,改造前接口 P95 是 240ms,改完后降到 58ms;DB QPS 峰值从 6200 降到 1400 左右。你如果想确认是否真的生效,最直观的方法就是对比压测前后的三项数据:缓存命中率、数据库 QPS、P95 延迟。只要这三个一起变好,基本就不是“假优化”。
最后提醒一句:Redis 不是万能药,缓存的是“结果”,不是“思考”。先把热点、过期、回源、兜底这四件事设计好,你的高并发接口才会真正稳。要是你还想看我下一期把“Redis 分片、Pipeline、Lua 原子脚本”也用同样方式拆开演示,评论区直接扣 1,我接着拍。需要更完整方案的话,官方和社区文档、以及一些现成工具方案都能参考;如果你想顺手看看一个可选方案,可以去 roxi.cc 自己对比一下。