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

二刷 黑马点评 分布式锁-redission

重入:
获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁
不可重试:
只能尝试一次
超时释放:
在加锁时增加了过期时间,可以防止死锁,有安全隐患
主从一致:
向集群写数据时,主机需要异步地将数据同步给从机

Redission

在Redis基础上实现的Java驻内存数据网络,提供一系列分布式Java常用对象和分布式服务
包括分布式锁的实现
![[Pasted image 20250716181153.png]]

RLock lock = redissonClient.getLock("anyLock");
锁的名称是anyLock,是全局唯一标识,当多个客户端或线程尝试获取相同名称的锁时,就会发生竞争关系
Rlock代表是可重入锁,同一线程能够多次获取同一把锁,不会出现死锁

可重入锁原理

使用一个state变量记录重入状态,当没有人持有这把锁,state=0,假如有人持有,state=1,当前持有这把锁的人再次持有这把锁时,state+1
也就是重入一次加一,释放一次减一,直到减少为0代表这把锁没有被持有

在分布式锁中,使用hash存储锁
加锁代码:
![[Pasted image 20250716182953.png]]

这里共有三个参数:
KEYS[1]:锁名称
ARGV[1]:线程唯一标识
ARGV[2]:锁自动释放时间
首先判断锁是否存在
不存在就直接获取锁

存在就判断是不是自己的是自己的就重入次数加一不是自己的则获取锁失败

释放锁代码:
![[Pasted image 20250716183305.png]]

先判断锁是不是自己的
不是自己的直接返回
是自己的重入次数减一
如果重入次数为0则直接释放锁
不为0说明还不能释放,重制有效期

MutiLock原理

在搭建redis集群和主从的过程中
当执行写命令,写在主机上时,主机会同步数据给从机,但是假如主机在还没来得及把数据写入从机的时候就宕机,哨兵会发现主机宕机,并选举一个slave成为Master,新的Master实际并没有锁信息,此时锁信息就丢失掉了。
![[Pasted image 20250716194549.png]]

为解决这个问题,提出了MutiLock,使用这把锁就不使用主从,每个节点有相同地位
这把锁的逻辑是需要写入每一个主从节点上,只有所有服务器都成功写入才是加锁成功,假设有一个节点挂了,在获取锁时只要有一个节点拿不到就是加锁失败
![[Pasted image 20250716194717.png]]

加锁原理

设置多个锁时,会把多个锁添加到一个集合,用while循环去不停尝试拿锁,但存在一个总加锁时间,这个时间是需要加锁的个数*1500ms,假设在时间内所有锁加锁成功才算成功,只要有线程加锁失败,就会再次重试
![[Pasted image 20250716195041.png]]

总结

  1. 可重入锁是如何防止死锁的?
    可重入锁允许同一线程多次获取同一把锁,通过计数器(state)记录重入次数。重入时递增,释放时递减,减至 0 才完全释放锁。这种机制避免了同一线程因重复请求同一锁而导致的阻塞,从而防止死锁。
  2. Redisson 的分布式可重入锁如何实现原子性?
    Redisson 使用 Lua 脚本实现分布式锁的原子性操作。加锁时,通过 Lua 脚本原子性地检查锁是否存在、是否自己持有以及递增重入次数;释放锁时,同样通过 Lua 脚本原子性地递减重入次数并判断是否释放锁,确保操作的原子性。
  3. 超时释放机制的安全隐患是什么?如何应对?
    超时释放可能导致锁提前释放,引发多个线程同时持有锁的问题。应对方法:
    合理设置超时时间,根据业务执行时间调整
    使用 watchdog 机制自动续期
    业务代码中做好幂等性处理
  4. Redisson 的 MultiLock 如何解决主从架构中的锁丢失问题?
    MultiLock 要求在多个独立节点上同时获取锁,只有全部获取成功才算加锁成功。即使主节点宕机,由于其他节点仍持有锁,新选举的主节点不会影响锁的有效性,从而避免锁丢失。
  5. MultiLock 加锁失败后的重试机制是怎样的?
    MultiLock 通过 while 循环不断尝试加锁,总加锁时间为锁数量 * 1500ms。若在该时间内所有锁均加锁成功,则加锁成功;否则失败,释放已获取的锁并重新尝试。这种机制平衡了性能和可靠性。
http://www.lryc.cn/news/590727.html

相关文章:

  • 基于Canal实现MySQL数据库数据同步
  • Alamofire 网络请求全流解析,通俗易懂
  • ai 编程工具,简单总结
  • Python脚本批量修复文件时间戳,根据文件名或拍摄日期
  • 达梦数据库CASE_SENSITIVE大小写敏感差异比较
  • 字段级权限控制场景中,RBAC与ABAC的性能差异
  • 【机器学习【6】】数据理解:数据导入、数据审查与数据可视化方法论
  • [NOIP][C++] 树的重心
  • 嵌入式单片机开发实战指南: 从RISC-V到TinyML全栈技术
  • 筑牢网络安全防线:DDoS/CC 攻击全链路防护技术解析
  • 权限隔离设计中实现字段级别的动态隐藏
  • 工作第一步建立连接——ssh
  • 【JavaScript】从事件流到事件委托
  • 再探多线程Ⅰ--- (创建思路+核心方法+代码样例)
  • [Mysql] Connector / C++ 使用
  • 二分查找算法(一)
  • 多目标优化|HKELM混合核极限学习机+NSGAII算法工艺参数优化、工程设计优化,四目标(最大化输出y1、最小化输出y2,y3,y4),Matlab完整源码
  • WP Force SSL Pro – HTTPS SSL Redirect Boost Your Website‘s Trust in Minutes!
  • 代码随想录算法训练营完结篇
  • 主流 TOP5 AI智能客服系统对比与推荐
  • Raydium CLMM 协议
  • Gradle vs Maven:构建工具世纪对决 —— 像乐高积木与标准模型之间的选择艺术
  • Transform的重要方法
  • excel分组展示业绩及增长率
  • 归一化与激活函数:深度学习的双引擎
  • 【WRFDA数据教程第一期】LITTLE_R 格式详细介绍
  • opencv 值类型 引用类型
  • 身份证号码姓名认证解决方案-身份证三要素API接口
  • Python+Selenium自动化
  • 【python】sys.executable、sys.argv、Path(__file__) 在PyInstaller打包前后的区别