怎么用缓存预热和降级方案应对流量高峰
结论:应对流量高峰的可靠做法是「提前把热点数据灌进缓存 + 准备好可一键触发的多级降级开关」,预热让缓存命中率稳定在 95% 以上,降级保证在缓存失效或下游故障时核心链路仍能返回结果。
缓存预热怎么做?
缓存预热的核心是「在流量到来前,把可预测的热点数据提前写进 Redis 和本地缓存」,而不是等第一个请求回源。
具体分三步:
- 圈出热点数据:活动开始前用离线任务统计近 7 天访问量 Top 5000 的 key,或按业务维度直接列出(如秒杀商品 ID 列表、首页栏目 ID)。这份清单要落库或放配置中心,可人工增删。
- 批量写入:应用启动完成后(Spring 的
ApplicationRunner或CommandLineRunner)异步触发预热任务,用 Redis Pipeline 批量写,单批 500~1000 个 key,避免单次 RTT 过高。也可以离线生成redis-cli --pipe的导入文件,10 万条 key 通常 10 秒内完成。 - 设好过期策略:TTL 用「基础值 + 随机抖动」,例如 30 分钟 + 0~300 秒随机,防止同一时刻批量失效造成缓存雪崩。对 Top 1000 的超级热点,改用逻辑过期:Redis 里不设 TTL,value 中带一个过期时间戳,读到过期时返回旧值并异步刷新。
结论:预热的目标是让活动开始前缓存命中率达到 95% 以上,且预热必须在流量到来前 10 分钟完成,留出容错时间。
缓存预热要注意哪些坑?
最容易踩的坑是预热把数据库打挂,或者预热的数据本身是错的。
- 限速预热:预热任务对数据库的查询要加并发上限,单实例并发控制在 4~8,全集群预热 QPS 不超过数据库承载上限的 30%。分批 sleep 100ms 比一次全量拉取安全。
- 防击穿:热点 key 失效瞬间会有大量请求同时回源。用单飞(singleflight,即同一 key 的并发回源只放行一个请求)或分布式锁,锁超时设 3 秒,拿不到锁的请求直接返回兜底值。
- 数据校验:预热完成后打印「计划写入数 / 实际写入数 / 失败数」三个指标,失败率超过 0.1% 就告警并重跑。
- 本地缓存同步:JVM 内本地缓存(如 Caffeine,
maximumSize=10000、expireAfterWrite=5s)在预热时也要一起填,否则第一批请求还是会打到 Redis。
降级方案怎么设计?
降级的前提是先给系统分级:P0 是下单、支付这类必须可用的链路,P1 是商品详情、库存查询,P2 是推荐、评论、排行榜。流量高峰时按 P2 → P1 → P0 的顺序逐级关闭。
触发条件要写死、可量化,推荐组合以下阈值:
- 接口 P99 响应时间连续 10 秒超过 500ms;
- 错误率 10 秒窗口内超过 5%;
- 线程池队列使用率超过 80%;
- 单机 QPS 超过压测容量的 70%。
工具上,Sentinel 或 Resilience4j 都能做熔断降级(Hystrix 自 2018 年起已停止新功能开发,不建议新项目使用)。降级动作分三类:读降级返回本地缓存或静态兜底数据;写降级把请求投进 MQ 削峰、异步落库;功能降级直接返回「当前人数过多,请稍后再试」的静态页,由 Nginx + Lua 直接吐出,不打到应用层。
结论:所有降级开关必须放在配置中心,支持 1 秒内动态生效,不能依赖重启发布。
预热和降级怎么配合?
两者是「一攻一守」:预热负责提高缓存命中率、减少回源,降级负责在预热失效或下游故障时守住底线。
配合的关键是给降级准备「有数据可返回」。具体做法是:预热时顺便把热点数据的精简版(只留 ID、名称、价格等 3~5 个字段)写进本地缓存和一份静态 JSON,降级时直接读这份数据,用户看到的页面不空白,只是少了实时库存、个性化推荐等非核心字段。
另外要设定优先级:缓存命中率跌破 90% 就先扩容 Redis 或加本地缓存,不要急着降级;只有当回源 QPS 超过数据库承载的 80% 时,才触发读降级。
怎么验证这套方案有效?
结论:不压测的预热和降级都是纸面方案,必须在预发环境做一次全链路演练。
演练步骤:用压测工具把单机 QPS 压到目标峰值的 1.2 倍,持续 10 分钟;观察缓存命中率是否保持 95% 以上、P99 是否低于 300ms;然后手动 kill 掉 Redis 主节点或注入 500ms 延迟,验证降级开关是否在 10 秒内自动触发、核心接口是否仍返回 200。演练后把实际触发的阈值和恢复时间记进预案文档,每季度复跑一次。
收束一句:预热解决「数据提前到位」,降级解决「坏了也能用」,两者都靠可量化阈值和动态开关落地,缺一个都扛不住真实流量高峰。
原文链接:https://www.gj0.com/thread-604.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。