当前位置: 首页 > news >正文

Redisson分布式锁会发生死锁问题吗?怎么发生的?

死锁发生的核心条件:互斥、持有并等待、不可剥夺、循环等待

关于基础锁(RLock)的死锁风险,主要来自两个层面:
1)客户端层面:如果两个线程互相等待对方持有的锁,且都不释放,就会形成典型的死锁。不过这种情况更多是业务逻辑设计问题,比如lock1和lock2嵌套获取的场景。
2)服务端层面:当Redis连接闪断时,看门狗线程无法续期但业务线程仍在运行,最终锁过期释放,而业务线程在finally块调用unlock时会误删新持有者的锁

🔒 一、基础锁(RLock)死锁场景

  1. 看门狗续期失败导致锁永久持有
  • 发生条件:
    • 业务线程持有锁期间,Redis连接发生闪断(如网络波动)
    • 看门狗线程因连接异常无法执行续期命令(pexpire
  • 结果:
    • 锁超时自动释放,但业务线程仍在运行
    • 其他线程可获取锁,出现多个线程并发操作临界资源
    • 原持有者执行unlock()时,因锁已易主,可能误删新持有者的锁
  1. 嵌套锁导致的循环等待
// 线程1
lockA.lock();
lockB.lock();
...
// 线程2 
lockB.lock();
lockA.lock();  // 形成循环等待 
  • 原理:
    若两个线程以相反顺序获取嵌套锁,且恰好在中间步骤阻塞,则形成死锁四要件(互斥、持有等待、不可剥夺、循环等待)

📚 二、读写锁(RReadWriteLock)死锁场景

读锁升级写锁

// 线程1(持有读锁)
rLock.readLock().lock();
rLock.writeLock().lock(); // 阻塞等待所有读锁释放 
// 线程2(持有读锁,同样尝试升级)
rLock.writeLock().lock(); // 互相等待对方释放读锁
  • 结果:
    所有持有读锁的线程都无法升级为写锁,且写锁请求阻塞,导致系统僵死

🔴 三、红锁(RedLock)的死锁风险

时钟漂移引发的锁重叠

  • 场景:
    • 节点A时钟过快,提前释放锁
    • 节点B时钟正常,仍认为锁有效
  • 结果:
    客户端1在节点A释放锁后,客户端2立即获取锁,但节点B仍保留旧锁数据,导致两客户端同时持有锁

⚖️ 四、公平锁(FairLock)的死锁陷阱

队列状态不一致

  • 场景:
    • 客户端A获取锁后发生长时间GC暂停
    • 看门狗续期失败,锁过期被删除
    • 客户端B获取锁并修改队列
  • 结果:
    客户端A恢复后仍认为自己是持有者,强制解锁破坏队列,后续线程陷入永久阻塞

🛡️ 五、最佳实践

锁类型死锁原因解决方案
基础锁看门狗续期失败设置合理超时时间(lock.tryLock(10, 30, TimeUnit.SECONDS)),避免依赖看门狗[4]
读写锁读锁升级写锁禁止锁升级,写锁需直接获取而非由读锁升级[1]
红锁时钟漂移使用NTP同步集群时间,并采用单调递增时钟计算有效期[1]
公平锁队列状态异常启用redisson-lockleaseTime参数,避免依赖看门狗续期[3]
通用方案嵌套锁循环等待全局统一锁获取顺序,或用MultiLock原子获取多锁[1]

💎 总结

  1. 死锁根源:
    • 锁续期机制与业务执行状态割裂(如网络闪断导致看门狗失效)[3]
    • 分布式环境时钟不一致(红锁场景)[1]
    • 锁设计违背安全原则(如读写锁升级)[1]
  2. 规避铁律:
    • 永远设置显式超时(即使启用看门狗)
    • 避免在锁内调用外部服务(防止长阻塞)
    • 使用tryLock而非lock,设置等待超时[4]

生产环境推荐:

  • 监控锁续期线程状态:Redisson.EXPIRATION_RENEWAL_MAP [3]
  • 定期扫描长期持有锁的客户端:redis-cli --eval check_long_hold_lock.lua
http://www.dtcms.com/a/363516.html

相关文章:

  • Aurobay EDI 需求分析:OFTP2 与 EDIFACT 驱动的汽车供应链数字化
  • UniApp 实现搜索页逻辑详解
  • uniapp H5预览图片组件
  • 年轻教师开学焦虑破解:从心出发,重构健康工作生活新秩序
  • uni-app 布局之 Flex
  • 第一讲、Kafka 初识与环境搭建
  • ImageMagick命令行图片工具:批量实现格式转换与压缩,支持水印添加及GIF动态图合成
  • windows系统离线安装Ollama、创建模型(不使用docker)、coze调用
  • 51c大模型~合集177
  • Swift 解法详解:LeetCode 369《给单链表加一》
  • 研发团队缺乏统一文档模板怎么办
  • 苹果开发中什么是Storyboard?object-c 和swiftui 以及Storyboard到底有什么关系以及逻辑?优雅草卓伊凡
  • 【后端】Docker 常用命令详解
  • 构建企业级区块链网络:基于AWS EC2的弹性、高可用解决方案
  • 2025软件测试面试热点问题,3天刷完你的软件测试就牛了
  • 不同编译器之间代码转换
  • Java学习笔记-零基础学MySQL(二)
  • QT C++传递 map 给qml 中访问的两种方式
  • 深度学习容器化部署
  • Nginx 调度算法全解析:从基础到高级的负载均衡策略
  • HOW - 在浏览器下载一个 Excel 表格文件
  • Qt Demo(3) 之 deepseek 帮我写的关于图像显示的小界面
  • 漫画短剧小程序系统开发:从0到1的核心架构与思路
  • Redis 缓存雪崩实战:从监控告警到3层防护的完整修复
  • 【读论文】美团开源MOE大模型LongCat-Flash
  • Pod自动重启问题排查:JDK 17 EA版本G1GC Bug导致的应用崩溃
  • 线上排查bug的命令
  • 企业微信员工聊天记录能看吗?合规管理三要素一次性说清
  • 企业微信怎么用能高效获客?拆解体检品牌如何实现私域营收提升
  • Windows 和 Linux 服务器 IP 与域名强制绑定方法