redis分布式锁

实现的三个核心要素:

加锁

setnx(key,1)

当一个线程执行setnx返回1,说明key原本不存在,该线程成功得到了锁;当一个线程执行setnx返回0,说明key已经存在,该线程抢锁失败。

解锁

del(key)

释放锁之后,其他线程就可以继续执行setnx命令来获得锁。

锁超时

如果一个得到锁的线程在执行任务的过程中挂掉,来不及显示地释放锁,这块资源将会永远被锁住,别的线程就再也进不来了。
设置超时时间这把锁就在一定时间后自动释放了。

expire(key,30)

伪代码如下

if(setnx(key,1) == 1){
	expire(key,30)
	try{
		do somethind....
	}finally{
		del(key)
	}
}

上面的伪代码存在三个致命问题:

1.setnx和expire的非原子性

在这里插入图片描述
节点1的setnx刚执行成功,还未执行expire指令,节点1宕机了。
这样,别的线程就再也无法获得锁了。
setnx指令本身不支持传入超时时间,但是set指令增加了可选参数,伪代码如下:

set(key,1,ex 30,nx)

查看这篇博客 https://blog.csdn.net/ningmengbaby/article/details/92088795
就知道上面指令的意思了。

2.del 误删

在这里插入图片描述
节点1成功得到了锁,并且设置超时时间是30秒。但是A执行很慢,过了30秒还没有执行完,这时候锁过期自动释放。线程B得到了锁。
在这里插入图片描述
线程A执行完,del释放锁,但此时线程B还么有执行完,线程A实际上删除的就是线程B加的锁。
在这里插入图片描述
解决方法:在del释放锁之前做一个判断,验证当前的锁是不是自己加的锁。
具体实现:在加锁的时候把当前的线程ID当做value,并在删除之前验证key对应的value是不是自己的线程ID。
加锁:

String threadId = Thread.currentThread().getId()
set(key threadId,ex 30,nx)

解锁:

if(threadId.equals(redisClient.get(key))){
	del(key)
}

但是,判断和释放锁是两个独立操作,不是原子性的。所以这一块可以用Lua脚本来实现。这里因为没有研究过就不阐述了。

3.出现并发的可能性

第二点我们避免了线程A误删掉key的情况,但是同一时间有A,B两个线程在访问代码块,仍然不完美。
解决方法:让获得锁的线程开启一个守护线程,用来给快要过期的锁“续航”。
在这里插入图片描述
当过去了29秒,线程A还没执行完,这时候守护线程会执行expire指令,为这把锁“续命”20秒。守护线程从第29秒开始执行,每20秒执行一次。
在这里插入图片描述
当线程A执行完任务,会显式关掉守护线程。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值