如何解决Redis热点Key失效引发的击穿_使用SETNX分布式锁实现互斥更新

云敏小哥_7534

云敏小哥_7534

2026-05-31

729人浏览

原创

直接用setnx实现互斥锁需搭配px过期时间、唯一锁值(如uuid)及lua脚本原子释放,否则无法解决缓存击穿;synchronized仅作用于单jvm,多实例下完全无效。

如何解决redis热点key失效引发的击穿_使用setnx分布式锁实现互斥更新

直接用 SETNX 实现互斥锁能解决缓存击穿,但多数人漏掉三个关键动作:抢锁后没二次查缓存、锁值没做客户端标识、释放锁没用 Lua 脚本校验。这三处一错,集群环境下照样击穿。

为什么单机 synchronized 在 Redis 击穿场景下完全无效

Java 的 synchronized 只锁当前 JVM 进程,而线上服务基本都是多实例部署。哪怕你写成 if (cache == null) { synchronized(this) { ... } },10 台机器每台都会各自执行一次 DB 查询——10 万并发进来,DB 照样被压垮 10 次。

更危险的是 volatile 变量,它连“读-改-写”的原子性都不保证,根本不能当锁用。分布式环境里,唯一可信的协调者是 Redis 本身。

  • 集群中每个节点都独立运行,本地锁对其他节点毫无约束力
  • 即使压测时单机表现正常,上线后必然复现击穿
  • 真正起作用的不是“加锁”这个动作,而是“所有节点都向同一个 Redis 实例申请同一把锁”

SETNX 必须搭配 PX 和唯一锁值才能用

SETNX 单独用等于裸奔。必须用 SET key value NX PX 30000 这种原子命令替代分步的 SETNX + EXPIRE,否则中间出错(比如网络中断、进程崩溃)会导致锁永远不释放。

锁值也不能硬写成 "1" 或 "true",得是每个客户端生成的唯一标识(如 UUID),否则 A 拿到锁还没写完,B 就误删了锁,A 回填时发现锁没了,可能重复写入或丢数据。

抖音实时热点榜
抖音实时热点榜

每小时追踪抖音热榜,抖音实时热点榜从创作者视角拆爆款、挖选题、预判趋势。

下载
  • 推荐命令:SET mutex:goods:1001 <uuid> NX PX 30000</uuid>
  • 锁 key 名建议带业务前缀,避免不同资源共用一个锁名导致误删
  • PX 时间要明显大于 DB 查询耗时(比如 DB 平均 200ms,锁设 30s),但不能过长(超 60s 易引发等待风暴)

抢到锁之后一定要再查一次缓存

这是最容易被跳过的一步。线程 A 抢到锁、去查 DB、写缓存、释放锁;线程 B 在 A 释放锁前就轮询到了,此时缓存已存在,B 应该直接返回,而不是再走一遍锁流程。

所以标准流程是:查缓存 → miss → 尝试 SET 加锁 → 成功则**再次查缓存** → 仍 miss 才查 DB → 写缓存 → 释放锁;失败则休眠后重试。

  • 伪代码关键判断:if (redis.get(key) != null) { return value; } 必须出现在加锁成功后的第一时间
  • 空值也要缓存(比如 SET goods:1001 "NULL" EX 60),否则穿透和击穿会一起爆发
  • 休眠时间别设太短(如 Thread.sleep(10)),50–100ms 更稳妥,避免 Redis 频繁收 SET/PX 请求

Lua 脚本释放锁是底线,不能省

用 DEL mutex:goods:1001 删除锁?只要服务在释放锁前崩溃,或者锁超时被自动清除,就可能让别的线程误删正在使用的锁。必须用 Lua 脚本做原子校验:

if redis.call("get", KEYS[1]) == ARGV[1] then
  return redis.call("del", KEYS[1])
else
  return 0
end

这段脚本确保只有加锁者才能删锁,且整个“判断+删除”不可分割。任何绕过它的释放方式(比如先 GET 再 DEL)在高并发下都不可靠。

真正卡住人的从来不是锁怎么加,而是锁怎么安全地放回去。生产环境里,90% 的锁相关故障都出在释放环节——要么没校验值,要么没用原子脚本,要么忘了放在 finally 块里。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

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

下载

相关标签:

redis 热点

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

相关专题

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

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

2023.08.11

1913

5

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

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

2023.10.07

2594

5

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

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

2023.11.02

4169

19

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

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

2023.11.14

3635

11

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

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

2024.04.02

6472

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

603

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

716

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5982

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1140

6

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习