Redis如何防止热点Key过期引发缓存击穿

胖伟小哥_8122

胖伟小哥_8122

2026-03-29

692人浏览

原创

用 setnx 加分布式锁是最直接的解法:通过原子性设置带业务前缀和过期时间的锁(如 lock:product:10086),配合 lua 脚本安全释放,可有效防止缓存击穿导致的数据库雪崩。

redis如何防止热点key过期引发缓存击穿

用 SETNX 加分布式锁是最直接的解法

缓存击穿本质是:一个热门 key 过期瞬间,大量请求同时穿透到数据库。不加控制的话,DB 就会收到几百上千次重复查询——哪怕只持续 1 秒,也足以拖垮服务。

用 SETNX(即 SET if Not eXists)在 Redis 里设一个临时锁是最常用、最轻量的方案。它天然支持原子性,且不需要额外组件。

  • 锁名建议带业务前缀和 key,比如 lock:product:10086,避免不同业务误删
  • 必须设置过期时间(EX 参数),否则锁进程崩溃或异常退出会导致死锁
  • 锁超时时间要略大于 DB 查询 + 写缓存的耗时,但别设太长(如超过 5 秒),否则等待线程积压严重
  • 释放锁不能简单 DEL,得用 Lua 脚本保证“判断+删除”原子性,否则可能删掉别人刚加的锁

逻辑过期比物理过期更抗压,但要注意脏数据窗口

不设 EX,改在 value 里存一个逻辑过期时间戳,是另一种主流思路。它把“是否过期”的判断从 Redis 移到应用层,彻底避开物理过期那一瞬的并发洪峰。

但它不是银弹:新值还没刷进缓存前,所有请求拿到的都是旧数据。对价格、库存等强一致性场景不适用,但对商品描述、用户资料这类容忍延迟的场景很友好。

  • 更新缓存必须加锁(仍用 SETNX),否则多个线程可能同时触发 DB 查询
  • 异步刷新推荐走线程池或消息队列,别用 Thread.start(),避免线程爆炸
  • 返回旧值时,要确保这个旧值本身没被其他逻辑误删或覆盖
  • 监控逻辑过期 key 的刷新耗时,如果某次 DB 查询卡住,会导致后续所有请求都返回陈旧数据

预热 + 随机 TTL 是预防型手段,适合已知热点

如果能提前知道哪些是热点(比如首页 banner、秒杀商品、排行榜前 20),就别等它过期再救火,主动预热更稳。

但光预热不够——如果所有热点 key 都设成 1 小时过期,那整点一到就是雪崩前奏。必须打散过期时间。

  • 预热时机选在低峰期(如凌晨 2 点),用脚本批量加载,避免和用户流量撞车
  • TTL 建议加随机偏移,比如基础 3600 秒,再 ±300 秒:3600 + random.randint(-300, 300)
  • 预热失败要告警,不能静默跳过;尤其注意预热用的 DB 查询是否走索引,别把预热变成慢查询源
  • 动态热点(如突发新闻、热搜话题)没法靠预热覆盖,得配合前面两种实时防御手段

别忘了检查锁的释放时机和重试逻辑

很多线上事故不是锁没加,而是锁加了但没正确释放,或者重试没设上限,导致线程堆积、连接耗尽。

比如用递归重试 get_data(key),一旦 DB 挂了,所有线程会无限循环 sleep + 重试,最终把连接池撑爆。

  • 重试最多 2–3 次,每次间隔递增(如 100ms → 200ms → 400ms),避免雪球效应
  • 锁释放必须放在 finally 块或使用 try-with-resources,确保异常时也能清理
  • 监控 lock key 的平均存活时间和命中率,如果大量锁超时未释放,说明 DB 查询慢或锁粒度太粗
  • 测试时一定要模拟锁冲突场景,光测单线程通过没意义
实际部署中,逻辑过期和分布式锁往往组合使用:先用逻辑过期扛住大部分流量,再用锁兜底防止并发重建。最难的不是写代码,是判断哪个 key 真正算“热点”——它得有高 QPS、低变更频次、且 DB 查询成本高。拿不准的时候,先上监控,再决定策略。
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2033

5

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.07

3054

5

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5707

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2468

6

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4118

6

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

2025.12.01

543

16

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4489

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

4035

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

7452

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习