空心|最全分布式锁设计方案( 三 )

3、小总结:
以上就是使用redisson做分布式锁的简单demo , 用起来十分的方便 。 上面是与springboot项目集成 , 直接用它提供的springboot的starter就好了 。 用它来做分布式锁的更多用法请移步至官网:redisson分布式锁 。
五、基于zookeeper实现1、zookeeper知识点回顾:
zookeeper有四种类型的节点:

  • 持久节点:默认的节点类型 , 客户端与zookeeper断开连接后 , 节点依然存在
  • 持久顺序节点:首先是持久节点 , 顺序的意思是 , zookeeper会根据节点创建的顺序编号
  • 临时节点:客户端与zookeeper断开连接后节点不复存在
  • 临时顺序节点:客户端与zookeeper断开连接后节点不复存在 , zookeeper会根据节点创建的顺序编号
2、基于zookeeper实现分布式锁的原理:
我们正是利用了zookeeper的临时顺序节点来实现分布式锁 。 首先我们创建一个名为lock(节点名称随意)的持久节点 。 线程1获取锁时 , 就在lock下面创建一个名为lock1的临时顺序节点 , 然后查找lock下所有的节点 , 判断自己的lock1是不是第一个 , 如果是 , 获取锁成功 , 继续执行业务逻辑 , 执行完后删除lock1节点;如果不是第一个 , 获取锁失败 , 就watch排在自己前面一位的节点 , 当排在自己前一位的节点被干掉时 , 再检查自己是不是排第一了 , 如果是 , 获取锁成功 。 图解过程如下:
空心|最全分布式锁设计方案zookeeper分布式锁原理
线程1创建了一个lock1 , 发现lock1的第一个节点 , 占锁成功;在线程1还没释放锁的时候 , 线程2来了 , 创建了一个lock2 , 发现lock2不是第一个 , 便监控lock1 , 线程3此时进行就监控lock2 。 直到自己是第一个节点时才占锁成功 。 假如某个线程释放锁的时候zookeeper崩了也没关系 , 因为是临时节点 , 断开连接节点就没了 , 其他线程还是可以正常获取锁 , 这就是要用临时节点的原因 。
说清楚了原理 , 用代码实现也就不难了 , 可以引入zookeeper的客户端zkClient , 自己写代码实现(偷个懒 , 自己就不写了 , 有兴趣的可以参考我zookeeper的文章 , 肯定可以自己写出来的) 。 不过有非常优秀的开源解决方案比如curator , 下面就看看curator怎么用 。
六、基于curator实现1、springboot整合curator:
  • pom.xml:
org.apache.zookeeper zookeeper 3.4.14 org.apache.curator curator-framework 4.2.0 org.apache.curator curator-recipes 4.2.0 org.seleniumhq.selenium selenium-java
  • application.yml:注意 , curator下面这些属性spring是没有集成的 , 也就是说写的时候不会有提示
curator:retryCount: 5 # 连接失败的重试次数retryTimeInterval: 5000 # 每隔5秒重试一次url: 192.168.2.43:2181 # zookeeper连接地址sessionTimeout: 60000 # session超时时间1分钟connectionTimeout: 5000 # 连接超时时间5秒钟
  • 配置类:读取application.yml中的属性 , 创建CuratorFramework实例
@Configurationpublic class CutatorConfig { @Value("${curator.retryCount}") private Integer retryCount; @Value("${curator.retryTimeInterval}") private Integer retryTimeInterval; @Value("${curator.url}") private String url; @Value("${curator.sessionTimeout}") private Integer sessionTimeout; @Value("${curator.connectionTimeout}") private Integer connectionTimeout; @Bean public CuratorFramework curatorFramework() {return CuratorFrameworkFactory.newClient(url, sessionTimeout, connectionTimeout,new RetryNTimes(retryCount, retryTimeInterval)); }}


推荐阅读