Zookeeper(58)如何在Zookeeper中實現分布式鎖?

在 Zookeeper 中實現分布式鎖是一種常見的用例。Zookeeper 提供了強一致性、高可用性的分布式協調服務,使得它非常適合用來實現分布式鎖。以下是詳細的步驟和代碼示例,展示如何在 Zookeeper 中實現分布式鎖。

1. Zookeeper 分布式鎖的基本原理

Zookeeper 分布式鎖的實現主要依賴于以下幾點:

  1. 臨時順序節點:每個客戶端在嘗試獲取鎖時,會在特定節點下創建一個臨時順序節點。
  2. 節點排序:所有客戶端創建的節點會按順序排列,最小的節點獲得鎖。
  3. 監視前一個節點:每個客戶端監視它前一個節點的變化,當前一個節點被刪除時,當前客戶端重新檢查自己是否是最小的節點,如果是,則獲得鎖。

2. 添加依賴

首先,需要在項目中添加 Zookeeper 的依賴。以下是 Maven 和 Gradle 的依賴配置:

Maven

pom.xml 中添加 Zookeeper 依賴:

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.7.0</version>
</dependency>
Gradle

build.gradle 中添加 Zookeeper 依賴:

dependencies {implementation 'org.apache.zookeeper:zookeeper:3.7.0'
}

3. 實現分布式鎖

以下是一個完整的實現分布式鎖的示例代碼。

ZookeeperClient.java
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;public class ZookeeperClient {private static final String ZK_ADDRESS = "localhost:2181";private static final int SESSION_TIMEOUT = 3000;private ZooKeeper zooKeeper;public void connect() throws Exception {zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("Received event: " + event);}});}public void close() throws InterruptedException {if (zooKeeper != null) {zooKeeper.close();}}public ZooKeeper getZooKeeper() {return zooKeeper;}public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();// 在這里可以測試分布式鎖client.close();} catch (Exception e) {e.printStackTrace();}}
}
DistributedLock.java
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;import java.util.Collections;
import java.util.List;public class DistributedLock {private static final String LOCK_ROOT = "/locks";private static final String LOCK_NODE = LOCK_ROOT + "/lock_";private ZooKeeper zooKeeper;private String lockPath;public DistributedLock(ZooKeeper zooKeeper) throws Exception {this.zooKeeper = zooKeeper;Stat stat = zooKeeper.exists(LOCK_ROOT, false);if (stat == null) {zooKeeper.create(LOCK_ROOT, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);}}public void acquireLock() throws Exception {lockPath = zooKeeper.create(LOCK_NODE, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println("Lock path: " + lockPath);while (true) {List<String> children = zooKeeper.getChildren(LOCK_ROOT, false);Collections.sort(children);String smallestChild = LOCK_ROOT + "/" + children.get(0);if (lockPath.equals(smallestChild)) {System.out.println("Acquired lock: " + lockPath);return;}String watchNode = null;for (int i = children.size() - 1; i >= 0; i--) {String child = LOCK_ROOT + "/" + children.get(i);if (child.compareTo(lockPath) < 0) {watchNode = child;break;}}if (watchNode != null) {final Object lock = new Object();Watcher watcher = new Watcher() {@Overridepublic void process(WatchedEvent event) {synchronized (lock) {lock.notifyAll();}}};Stat stat = zooKeeper.exists(watchNode, watcher);if (stat != null) {synchronized (lock) {lock.wait();}}}}}public void releaseLock() throws Exception {if (lockPath != null) {zooKeeper.delete(lockPath, -1);System.out.println("Released lock: " + lockPath);lockPath = null;}}public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();ZooKeeper zooKeeper = client.getZooKeeper();DistributedLock lock = new DistributedLock(zooKeeper);lock.acquireLock();// 模擬業務邏輯Thread.sleep(5000);lock.releaseLock();client.close();} catch (Exception e) {e.printStackTrace();}}
}

4. 代碼說明

ZookeeperClient 類

ZookeeperClient 類負責連接和關閉 Zookeeper 客戶端,并提供獲取 ZooKeeper 實例的方法。

DistributedLock 類

DistributedLock 類負責實現分布式鎖的邏輯,包括獲取鎖和釋放鎖。

  • acquireLock() 方法:嘗試獲取鎖,創建臨時順序節點,然后檢查自己是否是最小的節點。如果是,則獲得鎖;否則,監視前一個節點的變化。
  • releaseLock() 方法:釋放鎖,刪除自己創建的臨時順序節點。

5. 測試分布式鎖

DistributedLock 類的 main 方法中,創建 ZookeeperClient 實例并連接 Zookeeper,然后創建 DistributedLock 實例并嘗試獲取和釋放鎖。可以通過運行多個實例來測試分布式鎖的功能。

public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();ZooKeeper zooKeeper = client.getZooKeeper();DistributedLock lock = new DistributedLock(zooKeeper);lock.acquireLock();// 模擬業務邏輯Thread.sleep(5000);lock.releaseLock();client.close();} catch (Exception e) {e.printStackTrace();}
}

總結

  1. 添加依賴:在項目中添加 Zookeeper 的依賴。
  2. 實現 ZookeeperClient 類:負責連接和關閉 Zookeeper 客戶端,并提供獲取 ZooKeeper 實例的方法。
  3. 實現 DistributedLock 類:負責實現分布式鎖的邏輯,包括獲取鎖和釋放鎖。
  4. 測試分布式鎖:通過運行多個實例來測試分布式鎖的功能。

通過以上方法,可以在 Zookeeper 中實現分布式鎖,確保其高效穩定地運行。根據實際情況和需求,選擇適合你的實現方法并進行實施。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/70410.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/70410.shtml
英文地址,請注明出處:http://en.pswp.cn/web/70410.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

帆軟報表FineReport入門:簡單報表制作[擴展|左父格|上父格]

FineReport幫助文檔 - 全面的報表使用教程和學習資料 數據庫連接 點擊號>>JDBC 選擇要連接的數據庫>>填寫信息>>點擊測試連接 數據庫SQLite是帆軟的內置數據庫, 里面有練習數據 選擇此數據庫后,點擊測試連接即可 數據庫查詢 方法一: 在左下角的模板數據集…

后臺管理系統-項目初始化

認識vue-admin **核心交付:** 為什么要基于現成架子二次開發 什么是二次開發:基于已有的代碼(項目工程,腳手架)開進行新功能的開發 所以看懂已有的框架中的既有代碼,變得很重要了 1. 背景知識 后臺管理系統是一種最常見的應用模式,不同的管理系統之間有很多相似的地方…

DAY07 Collection、Iterator、泛型、數據結構

學習目標 能夠說出集合與數組的區別數組:1.是引用數據類型的一種2.可以存儲多個元素3.數組的長度是固定的 int[] arr1 new int[10]; int[] arr2 {1,2,3};4.數組即可以存儲基本類型的數據,又可以存儲引用數據類型的數據int[],double[],String[],Student[]集合:1.是引用數據類…

VLM(視覺語言模型)與DeepSeek R1(獎勵機制)如何結合

VLM&#xff08;視覺語言模型&#xff09;與DeepSeek R1&#xff08;獎勵機制&#xff09;如何結合 flyfish VLM的傳統訓練依賴于監督學習&#xff08;直接擬合問答對&#xff09;&#xff0c;而規則獎勵函數通常用于強化學習&#xff08;通過試錯和獎勵反饋優化策略&#xf…

從零開始構建一個語言模型中vocab_size(詞匯表大小)的設定規則

從零開始構建一個語言模型就要設計一個模型框架,其中要配置很多參數。在自然語言處理任務中,vocab_size(詞匯表大小) 的設定是模型設計的關鍵參數之一,它直接影響模型的輸入輸出結構、計算效率和內存消耗。 本文是在我前文的基礎上講解的:從零開始構建一個小型字符級語言…

計算機網絡之物理層——基于《計算機網絡》謝希仁第八版

(??? )&#xff0c;Hello我是祐言QAQ我的博客主頁&#xff1a;C/C語言&#xff0c;數據結構&#xff0c;Linux基礎&#xff0c;ARM開發板&#xff0c;網絡編程等領域UP&#x1f30d;快上&#x1f698;&#xff0c;一起學習&#xff0c;讓我們成為一個強大的攻城獅&#xff0…

實時股票行情接口與WebSocket行情接口的應用

實時股票行情接口與WebSocket行情接口的應用 實時股票行情接口是量化交易和投資決策的核心工具之一&#xff0c;行情接口的種類和功能也在不斷擴展。介紹幾種常見的行情接口&#xff0c;包括實時股票行情接口、Level2行情接口、WebSocket行情接口以及量化行情接口&#xff0c;…

圖論 之 BFS

文章目錄 3243.新增道路查詢后的最短距離1311.獲取你好友已觀看的視頻 BFS:廣度優先搜索&#xff08;BFS&#xff09; 是一種常用的算法&#xff0c;通常用于解決圖或樹的遍歷問題&#xff0c;尤其是尋找最短路徑或層級遍歷的場景。BFS 的核心思想是使用隊列&#xff08;FIFO 數…

ollama stream“:True django如何返回數據

在使用 Django 框架開發 Web 應用時&#xff0c;如果你想要通過 Ollama 流式返回數據&#xff0c;你可以通過 Django 的 HttpResponse 或者 StreamingHttpResponse 來實現。Ollama 主要用于處理文本生成任務&#xff0c;如聊天機器人、自動完成等&#xff0c;通常這些任務會產生…

為什么要用 const 和 let,而不是 var?

JavaScript 中有三種方式聲明變量&#xff1a;var、let 和 const。其中&#xff0c;var 是早期版本的 JavaScript 中的標準&#xff0c;但隨著 ECMAScript 6&#xff08;ES6&#xff09;引入了 let 和 const&#xff0c;var 的種種問題也顯現出來。今天&#xff0c;我們將探討為…

從零開始玩轉TensorFlow:小明的機器學習故事 2

你好&#xff0c;TensorFlow&#xff01;——從零開始的第一個機器學習程序 1. 為什么要寫這個“Hello, TensorFlow!”&#xff1f; 無論學習什么新語言或新框架&#xff0c;“Hello World!”示例都能幫助我們快速確認開發環境是否就緒&#xff0c;并掌握最基本的使用方式。對…

【Java八股文】10-數據結構與算法面試篇

【Java八股文】10-數據結構與算法面試篇 數據結構與算法面試題數據結構紅黑樹說一下跳表說一下&#xff1f;LRU是什么&#xff1f;如何實現&#xff1f;布隆過濾器怎么設計&#xff1f;時間復雜度&#xff1f; 排序算法排序算法及空間復雜度 數據結構與算法面試題 數據結構 紅…

Docker換源加速(更換鏡像源)詳細教程(2025.2最新可用鏡像,全網最詳細)

文章目錄 前言可用鏡像源匯總換源方法1-臨時換源換源方法2-永久換源&#xff08;推薦&#xff09;常見問題及對應解決方案1.換源后&#xff0c;可以成功pull&#xff0c;但是search會出錯 補充1.如何測試鏡像源是否可用2.Docker內的Linux換源教程 換源速通版&#xff08;可以直…

華為云deepseek大模型平臺:deepseek滿血版

華為云硅基流動使用Chatbox接入DeepSeek-R1滿血版671B 1、注冊&#xff1a; 華為云deepseek大模型平臺注冊&#xff1a;https://cloud.siliconflow.cn/i/aDmz6aVN 說明&#xff1a;填寫邀請碼的話邀請和被邀請的賬號都會獲得2000 萬 Tokens&#xff1b;2個帳號間不會與其他關聯…

抓包工具是什么?

抓包工具是一種用于捕獲和分析網絡數據包的軟件或硬件設備。它可以幫助用戶監控網絡通信過程&#xff0c;查看網絡中傳輸的數據內容、協議類型、源地址、目的地址等信息。以下是關于抓包工具的一些詳細解釋&#xff1a; 1. 主要功能 捕獲數據包&#xff1a;抓包工具能夠實時捕…

51c大模型~合集71

我自己的原文哦~ https://blog.51cto.com/whaosoft/12260659 #大模型推理加速技術的學習路線 EfficientQAT 可以在 41 小時內在單個 A100-80GB GPU 上完成對 2-bit Llama-2-70B 模型的量化感知訓練。與全精度模型相比&#xff0c;精度僅下降了不到 3%&#xff08;69.48 v…

OpenBMC:BmcWeb實例化App

BmcWeb是OpenBMC的一個核心模塊&#xff0c;對外負責響應Redfish請求&#xff0c;并且由于OpenBMC的Web使用的Redfish api&#xff0c;所以BmcWeb也是Web的后臺。 1.main函數 //src\webserver_main.cpp #include "webserver_run.hpp"int main(int /*argc*/, char**…

利用AI優化可再生能源管理:Python讓綠色能源更高效

利用AI優化可再生能源管理&#xff1a;Python讓綠色能源更高效 引言 在全球氣候變化和能源危機的背景下&#xff0c;可再生能源的利用變得尤為重要。然而&#xff0c;可再生能源的管理和優化面臨諸多挑戰&#xff0c;如能源生產的不穩定性和能源需求的波動性。幸運的是&#…

改BUG:Mock測試的時候,when失效

問題再現&#xff1a; 這里我寫了一測試用戶注冊接口的測試類&#xff0c;并通過when模擬下層的服務&#xff0c;但實際上when并沒有奏效&#xff0c;還是走了真實的service層的邏輯。 package cn.ac.evo.review.test;import cn.ac.evo.review.user.UserMainApplication; imp…

單片機 code RO-data RW-data ZI-data以及OTA學習

帶著問題去學習&#xff1a;這些數據是什么&#xff1f;分別放在哪里&#xff0c; 是什么&#xff1a;我個人的理解 code 和RO-data 分別是代碼和只讀數據&#xff0c;RW-data以及ZI-data分別是讀寫數據和初始化數據。 codeRO-data的大小正好是所占用ROM的大小&#xff0c;RO…