redis 实现分布式锁(一)
使用 SETNX + EXPIRE 实现分布式锁
首先线程在争夺锁的时候,使用 redis 的 setnx 命令,因为 redis 是单线程, 能保证 setnx 同一个 key 时,可以成功执行的命令只有一个,也就是说,只有一个线程能获取锁,其他线程在执行 setnx 失败后,即陷入阻塞状态,或者自旋等待。
当抢到锁,线程执行逻辑,执行完之后删除 key,进行锁释放,其他锁可恢复就绪状态,准备再执行 setnx 命令争抢锁。在此之下,当持有锁的线程发生了异常,或者宕机,就会造成锁无法释放的情况,此时其他线程就会永远无法得到锁。为了避免这种情况的发生,在 setnx key 时,同时指定一个过期时间,比如设置 10s,就算此时线程发生异常无法释放锁,在 10s 之后,key 会过期,锁就会自动释放。
setnx 说明:线程在执行 SETNX 时, 如果此时 key 不存在,则 SETNX 成功会返回 1,如果这个 key 已经存在,则会返回 0。
SETNX + 时间
在 setnx + expire 方案中,setnx 和 expire 两个命令分开执行了,不是原子操作。非原子操作,那两个命令执行的间隔,必然会可能发生其他的事,比如如果执行完 setnx,还没执行 expire 设置过期时间时,进程中断或者服务宕机,那么这个锁也会出现无法释放的情况,其他线程也就永远获取不到锁了。
此时 SETNX + 时间的方式,就可以将 setnx+expire 命令合并,形成原子操作,可以达到相同的效果。
形成原子操作后,也就避免了在两条期间的间隔期间发生其他的事。
这个时间,可以是指定系统时间,也可以指定过期时间,但此时会要求在多服务高可用部署下,每个服务器的系统时间要求是同步的。
版权声明: 本文为 InfoQ 作者【zarmnosaj】的原创文章。
原文链接:【http://xie.infoq.cn/article/e69f442a8bf306627f9601720】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论