持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
使用Lua脚本
简单说一下Lua脚本的特点: 首先Lua是一种轻量的脚本语言,用标准语言编写,并于源代码形式开放,非常适合嵌入别的程序里、Lua也提供了非常易于使用的扩展接口和机制、支持面向过程编程和函数式编程、自动内存管理等。
在全面提到,使用命令SETNX + EXPIRE实现分布式锁的方案中,是由于两个操作不是原子操作,会导致分布式锁无法实现的原因。
要保证原子性,还有一种方式可以实现,就是使用Lua脚本,
SET的扩展命令(SET EX PX NX)
除了使用Lua脚本保证SETNX + EXPIRE两条指令的原子性,还可以使用Redis的SET指令扩展参数:SET key value EX|PX NX|XX,这也是具有原子性的。
参数解释:
- 其中的EX,指的是key的过期时间
- PX和EX一样,指的过期时间,只是单位不一样,PX是毫秒,EX是秒。
- NX表示在指定key不存在时,才能成功执行命令
- XX和NX相反,是指定key存在时,才会成功执行命令,不然会失败
SET EX|PX NX|XX + 唯一value值(UUID)
SET的扩展命令(SET EX PX NX)方式的缺点:
- 存在一种情况:指定的key已经过期了,但是线程还没执行完逻辑,到期锁就自动释放,此时别的锁开始争抢锁并执行逻辑,这会使程序混乱。
- 在设置key时,没有规定只能设置的线程去释放,只要指定的key值,其他线程可以直接对key进行删除。
解决方案: 设置key时,线程生成一个随即不重复的数,比如生成UUID,然后临时保存起来。 删除key时,校验key中保存的value是否是当前线程临时保存的UUID,如果不是,则无法删除锁,只要是的情况下才能删除key释放锁。