redis分布式锁

分布式锁原理

分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,经常须要协调他们的动做。若是不一样的系统或是同一个系统的不一样主机之间共享了一个或一组资源,那么访问这些资源的时候,每每须要互斥来防止彼此干扰来保证一致性,在这种状况下,便须要使用到分布式锁。redis

 

使用setnx、getset、expire、del这4个redis命令实现

1.setnx 是『SET if Not eXists』(若是不存在,则 SET)的简写。 命令格式:SETNX key value;使用:只在键 key 不存在的状况下,将键 key 的值设置为 value 。若键 key 已经存在, 则 SETNX 命令不作任何动做。返回值:命令在设置成功时返回 1 ,设置失败时返回 0 服务器


2.getset 命令格式:GETSET key value,将键 key 的值设为 value ,并返回键 key 在被设置以前的旧的value。返回值:若是键 key 没有旧值, 也便是说, 键 key 在被设置以前并不存在, 那么命令返回 nil 。当键 key 存在但不是字符串类型时,命令返回一个错误。分布式


3.expire 命令格式:EXPIRE key seconds,使用:为给定 key 设置生存时间,当 key 过时时(生存时间为 0 ),它会被自动删除。返回值:设置成功返回 1 。 当 key 不存在或者不能为 key 设置生存时间时(好比在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。优化


4.del 命令格式:DEL key [key …],使用:删除给定的一个或多个 key ,不存在的 key 会被忽略。返回值:被删除 key 的数量。

blog

redis 分布式锁原理一

 

 过程分析:

    1.A尝试去获取锁lockkey,经过setnx(lockkey,currenttime+timeout)命令,对lockkey进行setnx,将value值设置为当前时间+锁超时时间;
    2.若是返回值为1,说明redis服务器中尚未lockkey,也就是没有其余用户拥有这个锁,A就能获取锁成功;
    3.在进行相关业务执行以前,先执行expire(lockkey),对lockkey设置有效期,防止死锁。由于若是不设置有效期的话,lockkey将一直存在于redis中,其余用户尝试获取锁时,执行到setnx(lockkey,currenttime+timeout)时,将不能成功获取到该锁;
    4.执行相关业务;
    5.释放锁,A完成相关业务以后,要释放拥有的锁,也就是删除redis中该锁的内容,del(lockkey),接下来的用户才能进行从新设置锁新值。
缺陷:
若是A在setnx成功后,A成功获取锁了,也就是锁已经存到Redis里面了,此时服务器异常关闭或是重启,将不会执行closeOrder,也就不会设置锁的有效期,这样的话锁就不会释放了,就会产生死锁。进程

 

redis 分布式锁原理2(优化版)

为了解决原理1中会出现的死锁问题,提出原理2双重防死锁,能够更好解决死锁问题。资源

 

 

 过程分析:

    1.当A经过setnx(lockkey,currenttime+timeout)命令能成功设置lockkey时,即返回值为1,过程与原理1一致;
    2.当A经过setnx(lockkey,currenttime+timeout)命令不能成功设置lockkey时,这是不能直接判定获取锁失败;由于咱们在设置锁时,设置了锁的超时时间timeout,当当前时间大于redis中存储键值为lockkey的value值时,能够认为上一任的拥有者对锁的使用权已经失效了,A就能够强行拥有该锁;具体断定过程以下;
    3.A经过get(lockkey),获取redis中的存储键值为lockkey的value值,即获取锁的相对时间lockvalueA
    4.lockvalueA!=null && currenttime>lockvalue,A经过当前的时间与锁设置的时间作比较,若是当前时间已经大于锁设置的时间临界,便可以进一步判断是否能够获取锁,不然说明该锁还在被占用,A就还不能获取该锁,结束,获取锁失败;
    5.步骤4返回结果为true后,经过getSet设置新的超时时间,并返回旧值lockvalueB,以做判断,由于在分布式环境,在进入这里时可能另外的进程获取到锁并对值进行了修改,只有旧值与返回的值一致才能说明中间未被其余进程获取到这个锁
    6.lockvalueB == null || lockvalueA==lockvalueB,判断:若果lockvalueB为null,说明该锁已经被释放了,此时该进程能够获取锁;旧值与返回的lockvalueB一致说明中间未被其余进程获取该锁,能够获取锁;不然不能获取锁,结束,获取锁失败。字符串

相关文章
相关标签/搜索