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
相关推荐#
作者:程序员小航
出处:https://www.cnblogs.com/liuzhihang/p/15018897.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
欢迎关注个人公众号:『 程序员小航 』
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!