美文网首页
Redis分布式锁

Redis分布式锁

作者: 尚亦汐 | 来源:发表于2018-08-08 22:04 被阅读0次

    用Redis实现分布式锁一般是用 setnx (set if not exist)来实现,如果可以设置成功,表示拿到锁,用完之后再用del来释放。

    setnx lock true
    OK
    ... do something critical ...
    del lock
    (integer) 1

    但是如果逻辑执行到中间出现异常了,可能会导致 del 指令没有被调用,这样就会陷入死锁,锁永远得不到释放。

    一般会在拿到锁之后给锁设置一个超时时间,如60s,这样即使出现异常,在60s后锁还是会被释放。

    setnx lock true
    OK
    expire lock 60
    ... do something critical ...
    del lock
    (integer) 1

    如果在 setnx 和 expire 之间发生异常,会导致 expire 得不到执行,也会造成死锁。

    最主要原因就是setnx和expire不是原子操作,在Redis 2.8 版本中作者加入了 set 指令的扩展参数,使得setnx和expire可以一起执行。

    set lock true ex 5 nx
    OK
    ... do something critical ...
    del lock

    多参数的set命令语法如下:
    SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]

    • EX seconds − 设置指定的到期时间(以秒为单位)。
    • PX milliseconds - 设置指定的到期时间(以毫秒为单位)。
    • NX - 仅在键不存在时设置键。
    • XX - 只有在键已存在时才设置。

    Redis分布式锁不适合执行时间很长的任务,因为如果执行时间比设定的失效时间长,就可能会造成同时有多个线程同时执行这一段业务逻辑。

    有一个稍微安全一点的解决方案,就是在set的时候将value设置为一个随机数uuid,在线程执行完任务释放锁的时候,要判断这个uuid是否跟上锁时候一致,如果一致则可以释放。

    以上做法可以保证一个线程上的锁不会被另外一个线程释放(当然,还需要保证匹配value的值和释放锁是一个原子操作才可以),但是如果锁是过期了自动释放,另外一个线程还是可以重新获得锁从而可以执行同一段任务。

    参考资料:
    [1]Redis深度历险 https://juejin.im

    相关文章

      网友评论

          本文标题:Redis分布式锁

          本文链接:https://www.haomeiwen.com/subject/emdzvftx.html