分布式锁的产生来源于分布式系统对共享资源的互斥访问,能够有效的解决共享资源访问。
- Redisson 是一个基于Redis实现的分布式锁,基本原理如下:px:设置过期时间。NX: 键key不存在则设置值。
set key value px milliseconds nx
- value 保证唯一性,如果value不唯一,可能会导致误解锁。
- 解锁时要验证value的值。考虑如下一种情况,如果a 客户端获取的锁到达了过期时间呗redis自动删除,但是此时还没有执行redis删除key操作,此时b客户端已经获取到一个同样key的锁,这会导致a客户端接下来的操作释放了b客户端正在使用的锁,导致发生错误。
- 这个方式也只作用于单节点的redis,也会有如下的缺点。
- 单节点的redis通过sentinel保证高可用,当主节点发生故障,从节点升级为主节点。
- 主从节点时通过复制的方式进行同步,当发生故障时主节点里有未同步到从节点的键就会导致锁的丢失。
- redLock是一个更好的实现方式,是为分布式高可用而存在。
redlock 的原理是存在多个master节点,这些节点之间不是主从也不是同一个集群关系。当获取一个锁的时候依次以同样的key和唯一的value向每个节点发送请求,当多个节点(N/2+1)成功则认为获取成功。这时候如果某个节点故障对整个锁的获取释放没有影响,达到高可用。具体步骤:
-
获取uninx时间戳,记录开始时间。
-
发送请求时为请求设置超时时间,超时时间要小于锁的过期时间。比如锁的过期是10s,请求超时时间是10到100毫秒这样。超时时间是避免当节点不可用时,客户端无用的等待。
-
用所获取的成功时间减去开始时间,就是锁获取的时间。锁过期时间减去获取锁的时间就是锁可用的使用时间,就是锁 的有效时间。
-
当大多数获取成功则锁获取成功。
-
由于硬件,网络等复杂性导致失败的情况,也会有比如节点设置锁成功,但客户端获取超时。也会有异常的发生,则无论成功失败,还是异常发生都要去每个节点依次去解锁