page contents

Redis实现分布式锁

轩辕小不懂 发布于 2021-11-27 11:49
阅读 576
收藏 0
分类:数据库
2525
Nen
Nen
- 程序员

分布式锁的三个核心要素

1、加锁

使用setnx来加锁。key是锁的唯一标识,按业务来决定命名,value这里设置为test。

1 setx key test
当一个线程执行setnx返回1,说明key原本不存在,该线程成功得到了锁;当一个线程执行setn
2、解锁
有加锁就得有解锁。当得到的锁的线程执行完任务,需要释放锁,以便其他线程可以进入。释放
1 del key
释放锁之后,其他线程就可以继续执行setnx命令来获得锁。
3、锁超时
锁超时知道的是:如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块
所以,setnx的key必须设置一个超时时间,以保证即使没有被显式释放,这把锁也要在一段时间
外指令,
1 expire key 30
上述分布式锁存在的问题
通过上述setnx 、del和expire实现的分布式锁还是存在着一些问题。
1、SETNX 和 EXPIRE 非原子性
假设一个场景中,某一个线程刚执行setnx,成功得到了锁。此时setnx刚执行成功,还未来得及
有设置过期时间,别的线程就再也无法获得该锁。
解决措施:
由于setnx指令本身是不支持传入超时时间的,而在Redis2.6.12版本上为set指令增加了可选参数
1 SET key value [EX seconds][PX milliseconds] [NX|XX]
EX second: 设置键的过期时间为second秒;
PX millisecond:设置键的过期时间为millisecond毫秒;
NX:只在键不存在时,才对键进行设置操作;
XX:只在键已经存在时,才对键进行设置操作;
SET操作完成时,返回OK,否则返回nil。
2、锁误解除
如果线程 A 成功获取到了锁,并且设置了过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过
行完成,线程 A 使用 DEL 命令来释放锁,但此时线程 B 加的锁还没有执行完成,线程 A 实际释
解决办法:
在del释放锁之前加一个判断,验证当前的锁是不是自己加的锁
请先 登录 后评论