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 路徑上加鎖。

加鎖之后:

  1. 創建了一個 /locks/lock_01 的持久節點,節點下有一個子節點 _c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000
  2. 節點 /locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000 是臨時節點
  3. 節點 /locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000 的數據是機器 IP 地址

加鎖源碼

PS:下面代碼截圖中的代碼風格就是 Curator 源碼的代碼風格。

入口

InterProcessMutex#internalLock

開始先從 threadData 中獲取當前線程,這里肯定是沒有的,所以進入 attemptLock 方法。

本方法中還包含了鎖重入的邏輯,后面也會介紹。

加鎖

LockInternals#attemptLock

核心部分就是這兩行:

  1. createsTheLock 創建臨時順序節點
  2. 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 中。

  1. 創建臨時節點,如果路徑存在,會創建成功,如果路徑不存在會創建失敗;
  2. 創建失敗后,先創建路徑,再創建節點。

總結

本篇文章主要介紹了基於 ZooKeeper 的分布式鎖框架 Curator 的使用,以及加鎖流程,源碼分析。

下面對內容做下總結:

重點需要關注的是:

  1. 基於 ZooKeeper 的分布式鎖,是使用的臨時順序節點,父節點是持久節點;
  2. 創建臨時節點時,父節點不存在,會先創建父節點(路徑);
  3. 鎖的組成結構為:對 /locks/lock_01 加鎖,實際鎖住的是 /locks/lock_01/_c_UUID-lock-序號,舉例為 /locks/lock_01/_c_cc4fc045-5a1e-4378-b3c7-8a8d3fb9a37c-lock-0000000000

相關推薦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM