ZooKeeper 分布式锁 Curator 源码 01:可重入锁
前言
一般工作中常用的分布式锁,就是基于 Redis 和 ZooKeeper,前面已经介绍完了 Redisson 锁相关的源码,下面一起看看基于 ZooKeeper 的锁。也就是 Curator 这个框架。

Curator 的锁也分为很多种,本文分析共享可重入锁。
考虑到如果文章篇幅较长,不太适合阅读,所以对文章做了适当的拆分。
环境配置

本机三个节点
版本:3.7.0
系统:macOS
安装方式:brew install zookeeper
Curator Maven 依赖版本:5.1.0
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
加锁示例

详细信息可参考官方文档。
加锁前

在加锁之前,ZooKeeper 仅有一个节点 /zookeeper。
加锁中
在 /locks/lock_01 路径上加锁。

加锁之后:
- 创建了一个
/locks/lock_01的持久节点,节点下有一个子节点_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000 - 节点
/locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000是临时节点 - 节点
/locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000的数据是机器 IP 地址
加锁源码
PS:下面代码截图中的代码风格就是 Curator 源码的代码风格。
入口
InterProcessMutex#internalLock

开始先从 threadData 中获取当前线程,这里肯定是没有的,所以进入 attemptLock 方法。
本方法中还包含了锁重入的逻辑,后面也会介绍。
加锁
LockInternals#attemptLock

核心部分就是这两行:
- createsTheLock 创建临时顺序节点
- internalLockLoop 判断是否创建成功
创建临时顺序节点
StandardLockInternalsDriver#createsTheLock

可以看出节点的 mode 是 CreateMode.EPHEMERAL_SEQUENTIAL,表示这是一个临时顺序节点!
进入 CreateBuilderImpl#forPath(java.lang.String, byte[])

client.getDefaultData() 就是本机 IP 地址。
这个 adjustPath 方法看名字就是在调整路径之类的。会生成一个 UUID 拼接到 /locks/lock_01 中,变成 /locks/lock_01/_c_UUID-lock-。
因为创建的是临时顺序节点,所以会自动在后面添加顺序,最终变为 /locks/lock_01/_c_UUID-lock-0000000000。
具体创建节点是在 CreateBuilderImpl#pathInForeground 中。

- 创建临时节点,如果路径存在,会创建成功,如果路径不存在会创建失败;
- 创建失败后,先创建路径,再创建节点。
总结
本篇文章主要介绍了基于 ZooKeeper 的分布式锁框架 Curator 的使用,以及加锁流程,源码分析。
下面对内容做下总结:

重点需要关注的是:
- 基于 ZooKeeper 的分布式锁,是使用的临时顺序节点,父节点是持久节点;
- 创建临时节点时,父节点不存在,会先创建父节点(路径);
- 锁的组成结构为:对
/locks/lock_01加锁,实际锁住的是/locks/lock_01/_c_UUID-lock-序号,举例为/locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000
相关推荐
- Redisson 分布式锁源码 11:Semaphore 和 CountDownLatch
- Redisson 分布式锁源码 10:读写锁
- Redisson 分布式锁源码 09:RedLock 红锁的故事
ZooKeeper 分布式锁 Curator 源码 01:可重入锁的更多相关文章
- ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放
ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 ...
- ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁
前言 在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的? 并发加锁 先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点. ...
- ZooKeeper 分布式锁 Curator 源码 04:分布式信号量和互斥锁
前言 分布式信号量,之前在 Redisson 中也介绍过,Redisson 的信号量是将计数维护在 Redis 中的,那现在来看一下 Curator 是如何基于 ZooKeeper 实现信号量的. 使 ...
- redis实现分布式锁需要考虑的因素以及可重入锁实现
死锁 错误例子 解决方式 防止死锁 通过设置超时时间 不要使用setnx key expire 20 不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了 reidis2 ...
- ReentrantLock可重入锁——源码详解
开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...
- ReentrantLock(重入锁)简单源码分析
1.ReentrantLock是基于AQS实现的一种重入锁. 2.先介绍下公平锁/非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁 非公平锁是指多个线程获取锁的顺序并不是按照申 ...
- redis分布式锁-可重入锁
redis分布式锁-可重入锁 上篇redis实现的分布式锁,有一个问题,它不可重入. 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞. 同一个 ...
- java高并发系列 - 第12天JUC:ReentrantLock重入锁
java高并发系列 - 第12天JUC:ReentrantLock重入锁 本篇文章开始将juc中常用的一些类,估计会有十来篇. synchronized的局限性 synchronized是java内置 ...
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
随机推荐
- 火币HBAI量化币圈唯一免费量化炒币机器人
量化交易是一种投资方法.以先进的数学模型替代人为的主观判断,利用计算机技术从庞大的历史数据中海选能带来超额收益的多种"大概率"事件以制定策略,极大地减少了投资者情绪波动的影响,避免 ...
- Django中数据库操作相关的错误
问题:字段修改属性发生错误 1> >python manage.py makemigrations You are trying to add a non-nullable field ' ...
- .NET平台系列16 .NET5/Asp.Net Core 在全球Web框架权威性能测试 Web Framework Benchmarks 中的吊炸天表现
系列目录 [已更新最新开发文章,点击查看详细] TechEmpower Web Framework Benchmarks 是许多Web应用程序框架执行基本任务(如JSON序列化.数据库访问和服 ...
- Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息。
Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息. 本文链接:https://blog.csdn.net/qq_38161040/art ...
- 优雅关闭springboot应用
1.添加钩子函数,钩子函数中指定要调用的方法 @PostConstruct public void run() { this.zkClient.start(this); this.schedulerS ...
- 重新整理 .net core 实践篇—————3种配置验证[十四]
前言 简单整理一些配置的验证. 正文 配置的验证大概分为3类: 直接注册验证函数 实现IValidteOptions 使用Microsoft.Extensions.Options.DataAnnota ...
- return true 和 return false 和 return
1.return false:相当于终止符,干了3件事,阻止默认行为,取消事件冒泡,以及停止回调执行立即返回: 2.return:停止回调执行立即返回: 3.return true:相当于执行符,继续 ...
- JAVA并发(7)-并发队列PriorityBlockingQueue的源码分析
本文讲PriorityBlockingQueue(优先阻塞队列) 1. 介绍 一个无界的具有优先级的阻塞队列,使用跟PriorityQueue相同的顺序规则,默认顺序是自然顺序(从小到大).若传入的对 ...
- Linux学习笔记:Linux命令之权限管理命令
权限管理命令 chmod(重要) 命令名称:chmod 英文原意:change the permissions mode of a file 执行权限:所有用户 功能描述:改变文件或目录权限 语法:c ...
- 使用fiddler工具模拟弱网环境
1.使用CTRL+R快捷键调出设置窗口 2.CTRL+F搜索"if (m_SimulateModem)",如下图 3.设置 // 这里修改每KB上传时候的延迟速度,以ms为单位 ...