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
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值