1.分布式锁的实现方式?
1.基于数据库实现 -mysql行锁
2.基于zookeeper -CP模式
3.基于Redis setnx实现 -AP模式
4.Redis框架 Redission,RedisLock
要求:保证一致性 zk实现分布式锁
保证可用性 redis实现分布式锁
2.Zookeeper实现分布式锁
原理:zookeeper节点路径不能重复,保证唯一性,通过临时节点+事件通知来实现。
多个jvm在zk上同时创建一个相同的临时节点,有zk节点路径的唯一性,只有一个jvm会创建成功,其他jvm会尝试重试,如果尝试多次创建临时节点失败。就会订阅当前临时节点,然后变为阻塞状态,当jvm01业务执行完释放锁(调用close()方法)因为是临时节点,所以调用close方法时就会删除zk上对应的临时节点,因为在zk上有事件通知,删除掉节点会同时向订阅了当前临时节点的其他jvm发送通知,唤醒其他正在阻塞的jvm参与锁的竞争。
获取锁成功但是由于业务逻辑超时一直不释放情况下怎么解决?
依靠zk自身的sessionTimeout来删除节点释放锁,防止其他的jvm一直阻塞等待,将业务代码全部回滚,使用手动事务。
zookeeper实现分布式锁如何避免羊群效应?
羊群效应:当参与同一个锁竞争的jvm数量很大时,第一个jvm获取到锁,逻辑执行完释放锁,这时候zkServer就要去唤醒其余的数量很大的阻塞状态的jvm,可能唤醒到一半的时候其他进程已获取到锁,成本很高,所以要采用临时顺序节点的方式。
- 基于临时顺序节点实现分布式锁:
先创建一个根路径,多个jvm在根路径下创建多个顺序节点,当某个jvm创建的临时顺序节点最小时,代表当前jvm获取锁成功,jvm02获取锁失败,就会订阅前一个节点,即jvm01,当01释放锁删除01节点后,jvm02成为最小的临时顺序节点,获取锁成功,jvm03以此类推,订阅前一个节点,当前一个节点释放锁,删除节点,当前节点变为最小的临时顺序节点,获取锁成功。相当于juc中的公平锁,这样在唤醒的时候不必唤醒所有的节点,只需唤醒一个节点即可。
标签:事务,zk,临时,jvm,唤醒,节点,分布式 From: https://www.cnblogs.com/huang580256/p/17288991.html