讲师中心 微信公众号

工具推荐

视频效率加速
Seko
Seko

AI短剧一键生成成片

立刻MV
立刻MV

低成本歌曲 MV、视频生成

剧云
剧云

中文短剧剧本制作平台

Laper
Laper

剧本策划到成片协作

Redis如何避免分布式锁死锁引发的击穿瘫痪

千杰君_3451

千杰君_3451

发布时间:2026-03-21 12:37:02

|

778人浏览过

|

来源于php中文网

原创

Redis分布式锁死锁主因是锁身份失效后误删他人锁:SET加锁用唯一client_id,但业务超时导致锁过期,原线程仍用旧id解锁,删掉新持有者锁;必须用Lua原子解锁、独立守护线程续期、显式校验client_id。

redis如何避免分布式锁死锁引发的击穿瘫痪

Redis分布式锁为什么一加锁就死锁?

根本原因不是锁没释放,而是加锁和续期逻辑没对齐——SET 命令设了过期时间,但业务执行超时后锁自动过期,其他节点抢锁成功,而原线程还不知道,继续执行并尝试用错误的锁标识去 DEL,结果删掉别人刚持有的锁,导致后续多个节点同时写同一资源。这不是“锁没释放”,是“锁身份失效了还在用”。

常见错误现象:redis.clients.jedis.exceptions.JedisDataException: ERR Error running script (call to f_...): @user_script:1: user_script:1: attempt to access a non local key(Lua 脚本里用了非 EVAL 传入的 key)、或日志里反复出现「获取锁成功但业务未执行完」、「同一时刻两个服务都进了临界区」。

  • 必须用原子命令加锁:SET key random_value EX seconds NX,其中 random_value 是客户端唯一标识(如 UUID),不能用固定字符串
  • 续期不能靠后台线程盲等:要用独立的守护线程,定期检查业务是否还活着,并只对「自己加的锁」调用 EVAL 脚本续期
  • 解锁必须用 Lua 脚本保证原子性:EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock_key client_id

Redlock 真的能防止单点故障引发的死锁吗?

不能。Redlock 的设计目标是提升「锁服务可用性」,不是解决「锁误删」或「业务超时」问题。它在 Redis 集群部分节点失联时仍可能返回加锁成功,但此时已无法保证强一致性;更关键的是,它没改变单个锁的生命周期管理逻辑,续期、解锁、异常中断这些环节的坑一个都没少。

使用场景:只有当你有 5 个完全独立部署的 Redis 实例(不同物理机、不同网络分区),且容忍 TTFB(Time To Fail Back)在毫秒级波动时,Redlock 才比单实例略稳;绝大多数微服务架构下,它反而增加运维复杂度和时钟漂移风险。

  • Redlock 的 clock drift 补偿值(通常设为总耗时的 2%)极易被低估,尤其在容器化环境里,time() 调用可能因 CPU 节流跳变
  • 客户端需向 ≥3 个节点发起 SET 请求,任意一个失败就重试,这会放大网络抖动影响,反而提高锁延迟
  • 主流 SDK(如 Lettuce、Jedis)默认不内置 Redlock 实现,手写容易漏掉 quorum 判断或过期时间归一化

用 Redisson 的 RLock 就万事大吉?

不是。Redisson 的 RLock 确实封装了自动续期(watchdog)、可重入、公平锁等能力,但它默认的看门狗续期周期是 30 秒,而这个值写死在 Config.lockWatchdogTimeout 里——如果你的业务方法平均耗时 45 秒,watchdog 在第 30 秒续一次,第 60 秒才续第二次,中间那 15 秒锁就空窗了。

性能影响:watchdog 是通过 Netty 定时任务驱动的,每 10 秒扫一次待续期锁(可配),如果并发持有锁的客户端多,这个定时任务本身会成为瓶颈;另外,RLock.lockInterruptibly() 在中断时不会自动解锁,得手动 unlock(),否则锁残留。

  • 务必显式设置 Config.setLockWatchdogTimeout(60_000),值应 > 最长可能业务耗时 × 1.5
  • 避免在 try 块外写 unlock():必须用 try-finally 或 try-with-resources(配合 RLock 的 autoUnlock 模式)
  • 不要把 RLock 当作跨服务事务协调器:它不保证多个 key 的原子性操作,比如「扣库存 + 写订单」仍需靠业务层补偿或本地消息表

真正该盯住的三个脆弱点

所有分布式锁方案都会在「锁标识一致性」「时间窗口对齐」「异常路径覆盖」这三处漏风。最容易被忽略的是第三个:90% 的死锁瘫痪不是发生在正常流程,而是在 catch 块里忘了 unlock(),或在 finally 里调用了解锁却没判断锁是否属于自己加的。

比如 Spring AOP 切面加锁时,如果切点抛出 RuntimeException,而切面没做 try-catch,unlock() 根本不会执行;又比如用 Future.get(timeout, TimeUnit) 做超时控制,timeout 触发后线程被中断,但锁对象还握在原线程手里,没人通知它该释放。

  • 所有解锁操作前,必须校验当前锁的 value 是否等于本客户端的 client_id
  • 加锁时传入的 leaseTime 不要依赖默认值,明确写成 lock.tryLock(3, 30, TimeUnit.SECONDS) 这类带等待+持有时间的组合
  • 监控项不能只看「加锁成功率」,要加一条:「持有锁但未触发续期的锁数量」,这个指标突增就是 watchdog 失效的早期信号

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

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2911

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

517

2026.01.26

什么是分布式
什么是分布式

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

2173

2023.08.11

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

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

3614

2023.10.07

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1069

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3420

2023.10.25

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1898

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

3104

2023.09.04

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

60

2026.11.06

热门下载

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

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn