Redis分布式锁

书中人 2019年05月19日 1,735次浏览

redis分布式锁主要是基于setnx这个命令,nx和px,nx设置时发现redis中存在返回0否则返回1,px可以设置超时时间。

这个时候就会有一个问题就是如果一个执行出现超过了redis的px超时时间,那么他的锁就可能被其他线程夺走,执行完会出现线程安全问题,

不成熟的解决方案,就是执行完之后在进行判断一下是否是自己持有锁,如果不是就放弃执行结果,否则就提交成功(cas原理)。

Reids实现分布式锁

1.根据lockKey区进行setnx(set not exist,如果key值为空,则正常设置,返回1,否则不会进行设置并返回0)操作,如果设置成功,表示已经获得锁,否则并没有获取锁。
2.如果没有获得锁,去Redis上拿到该key对应的值,在该key上我们存储一个时间戳(用毫秒表示,t1),为了避免死锁以及其他客户端占用该锁超过一定时间(5秒),使用该客户端当前时间戳,与存储的时间戳作比较。
3.如果没有超过该key的使用时限,返回false,表示其他人正在占用该key,不能强制使用;如果已经超过时限,那我们就可以进行解锁,使用我们的时间戳来代替该字段的值。
4.但是如果在setnx失败后,get该值却无法拿到该字段时,说明操作之前该锁已经被释放,这个时候,最好的办法就是重新执行一遍setnx方法来获取其值以获得该锁。

Zookeeper实现分布式锁

基于临时顺序节点:
1.客户端调用create()方法创建名为“locknode/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。
2.客户端调用getChildren(“locknode”)方法来获取所有已经创建的子节点。
3.客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点是所有节点中序号最小的,那么就认为这个客户端获得了锁。
4.如果创建的节点不是所有节点中序号最小的,那么则监视比自己创建节点的序列号小的最大的节点,进入等待。直到下次监视的子节点变更的时候, 再进行子节点的获取,判断是否获取锁。释放锁的过程相对比较简单,就是删除自己创建的那个子节点即可。