长春市做网站推广,如何部署php网站,哔哩哔哩网页版入口,怎么样做问卷网站目录
获取锁#xff1a;
释放锁#xff1a;
Lua脚本#xff1a;
Redisson 分布式锁是#xff0c;满足分布式系统或集群模式下多进程可见并且互斥的锁#xff0c;因为我们熟知的java中的锁只是在单体架构下单个jvm中才会生效#xff0c;如果部署了多个jvm则会导致新的…目录
获取锁
释放锁
Lua脚本
Redisson 分布式锁是满足分布式系统或集群模式下多进程可见并且互斥的锁因为我们熟知的java中的锁只是在单体架构下单个jvm中才会生效如果部署了多个jvm则会导致新的并发问题。
对于分布式锁我们要确保的五个基本特征多进程可见性、互斥性、高可用、高性能和安全性
分布式锁的实现常见的有三种Mysql、Redis和Zookeeper 这里说一下redis实现分布式锁的操作
获取锁
互斥确保只有一个线程获取到锁
非阻塞式尝试一次成功返回true,失败返回false 释放锁 代码层面实现一下
获取锁键设置成业务名字这里拼接了两个字符串值的话设置成线程id并设置超时时间 释放锁
直接删除即可 这种情况还是会出现一些问题
在极端情况下如果线程1获取到锁但是线程1发生了阻塞阻塞期间锁超时释放然后此时线程2获取到锁线程1又醒了之后将线程2获取的锁释放了这时候线程3又进来了又会出现线程问题 结局思路就是在释放锁的时候将储存的线程id取出来上锁的时候值已经存为线程id判断是否为当前线程如果不是就不能释放只有是当前线程自己的锁才能释放id。
但是这种情况又会在分布式和集群下出现问题因为线程id是在jvm中维护的一个递增数解决办法是生产一个uuid拼接线程号表示线程标识后续判断使用这个新的唯一标识。 当然到这里还没完
如果当线程1判断锁是否为自己之后在准备释放锁的过程中线程阻塞然后锁超时释放这时候别的线程2来获得到锁线程1阻塞结束就还是会把线程2的锁释放掉这里就需要确保一下操作的原子性 Lua脚本
这里Redid的事务只能确保原子性无法保证事务的一致性这里通过lua脚本实现
lua脚本教程地址可参考Lua 教程 | 菜鸟教程
脚本执行redsi命令可以通过如下命令来实现
redis.call(set,name,jack) 等价于redis中的set name call
Redis调用lua脚本如下 脚本也可以通过参数传递如下 通过lua脚本实现如下功能 lua脚本如下 再Java中可以通过redisTemplate调用lua脚本通过execute方法 使用时可以新建一个lua脚本文件将脚本写入然后通过DefaultRedisScript的setLocation方法设置脚本位置 然后通过redisTemplate调用execute执行脚本将脚本和参数传入这就实现了判断释放锁代码的原子性将多行代码变成了一行 当然给予setnx的分布式锁还是存在下面问题
不可重入同一个无法多次获得同一把锁不可重试获取锁只尝试一次就返回没有重试机制超时释放超时释放虽然可以避免死锁但是如果业务时间耗时较长也会导致锁释放存在安全隐患主从一致性如果redis提供了主从集群主从同步存在延迟当主宕机时如果从同步主中的锁数据回出现问题
为了解决这些问题redisson提供的这些服务点击下方跳转redisson笔记
Redisson
Redisson实现分布式锁看门狗机制-CSDN博客