【ZooKeeper學習筆記】

1. ZooKeeper基本概念

Zookeeper官網:https://zookeeper.apache.org/index.html

  • Zookeeper是Apache Hadoop項目中的一個子項目,是一個樹形目錄服務
  • Zookeeper翻譯過來就是動物園管理員,用來管理Hadoop(大象)、Hive(蜜蜂)、Pig(小豬)的管理員,簡稱zk
  • Zookeeper的本質是一個分布式的、開源的、提供分布式應用程序協調服務的組件
  • Zookeeper提供的主要功能有:
    • 配置管理
    • 分布式鎖
    • 集群管理

2. ZooKeeper常用命令

2.1 ZooKeeper數據模型

在正式介紹Zookeeper的常用命令之前,我們先來了解一下Zookeeper的相關數據模型:

  • Zookeeper的是一個樹形目錄服務,其數據模型與unix文件系統目錄樹類似,是一個層次化的結構
  • 這里面的每一個節點都被稱為ZNode,每個節點上都會保存自己的數據以及元數據信息
  • 節點也可以擁有子節點,同時允許少量數據(1MB)存儲在該節點之下
  • 節點類型大致可以分為如下四類:
    • PERSISTENT:持久化節點
    • EPHEMERAL:臨時節點 -e
    • PERSISTENT_SEQUENTIAL:持久化順序節點 -s
    • EPHEMERAL_SEQUENTIAL:臨時順序節點 -e -s

2.2 ZooKeeper常用命令

Zookeeper是一個常見的客戶端-服務器模型,我們可以使用命令行或者JavaAPI的方式充當客戶端進行訪問,其架構如下圖所示:

  • 服務端命令:
  1. ./zkServer.sh start啟動zookeeper服務

image.png

  1. ./zkServer.sh status查看zookeeper服務運行狀態

image.png

  1. ./zkServer.sh restart重啟zookeeper服務

image.png

  1. ./zkServer.sh stop關閉zookeeper服務

image.png

  • 客戶端命令:
  1. ./zkCli.sh -server ip:port連接指定的zookeeper服務(如連接本地可忽略選項直接使用./zkCli.sh)

image.png

  1. quit退出客戶端交互界面

image.png

  1. help查看命令幫助

image.png

  1. ls 目錄查看指定目錄下的znode節點

image.png

  1. ls -s 目錄查看節點詳細信息

image.png

  1. create znode [value]創建znode節點(可以攜帶data)

image.png

  1. create znode -e [value]創建臨時節點(會話結束后消失)
  2. create znode -s [value]創建順序節點

image.png

  1. get znode查看節點攜帶數據

image.png

  1. set znode value設置節點數據

image.png

  1. delete znode刪除指定的znode節點(必須為空)

image.png

  1. deleteall znode刪除指定的znode節點及其子節點

image.png

2.3 ZooKeeper的JavaAPI操作

2.3.1 Curator介紹

Curator:是一個Zookeeper的Java客戶端庫

  • 常見的Zookeeper Java客戶端有如下幾種:
    1. 原生JavaAPI
    2. ZkClient
    3. Curator
  • Curator的目標就是簡化Zookeeper客戶端的使用
  • Curator項目最初有Netflix公司研發,后來捐給了Apache基金會,成為頂級項目

Curator官網:http://curator.apache.org/

2.3.2 Curator API操作
2.3.2.1 建立連接

我們可以使用CuratorFrameworkFactory靜態工廠類進行創建,可以通過如下兩種方式配置:

  1. 使用newClient()方法
  2. 使用build()方法

下面我們就給出對應兩種代碼的實現方式:
newClient:

/*** ZooKeeper測試類*/
public class ZooKeeperTest {private CuratorFramework client = null;@Beforepublic void initByNewClient() {CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181",3000,3000,new ExponentialBackoffRetry(3000, 1));this.client = client;this.client.start();}
}

build:

/*** ZooKeeper測試類*/
public class ZooKeeperTest {private CuratorFramework client = null;@Beforepublic void init() {CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181").sessionTimeoutMs(3000).connectionTimeoutMs(3000).retryPolicy(new ExponentialBackoffRetry(3000, 1)).namespace("").build();client.start();this.client = client;}
}

其中各個配置項含義如下:

  • connectString:連接字符串,配置服務器地址,格式為ip:port
  • sessionTimeoutMs:會話超時時間
  • connectionTimeoutMs:連接超時時間
  • retryPolicy:重試策略
  • namespace:設置根目錄位置
2.3.2.2 創建節點

創建節點有如下常見的四種方式:
Case1:創建節點(不攜帶數據)

@Test
public void testCreate1() throws Exception {String path = client.create().forPath("/app1");System.out.println(path);
}

Case2:創建節點(攜帶數據)

@Test
public void testCreate2() throws Exception {String path = client.create().forPath("/app2", "curator java api".getBytes());System.out.println(path);
}

Case3:創建多級節點

@Test
public void testCreate4() throws Exception {client.create().creatingParentsIfNeeded().forPath("/test/test1/test2");
}

Case4:創建節點并指定類型

@Test
public void testCreate3() throws Exception {client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");client.create().withMode(CreateMode.PERSISTENT).forPath("/app4");client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/app5");client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/app6");
}
2.3.2.3 刪除節點

刪除節點有如下常見的兩種方式:
Case1:刪除節點(不含子節點)

@Test
public void testDelete() throws Exception {client.delete().forPath("/app1");
}

Case2:刪除節點(遞歸刪除子節點)

@Test
public void testDeleteAll() throws Exception {client.delete().deletingChildrenIfNeeded().forPath("/test");
}
2.3.2.4 查詢節點

查詢節點有如下常見的三種方式:
Case1:查詢子節點信息

@Test
public void testGetChildren() throws Exception {List<String> childrenList = client.getChildren().forPath("/");System.out.println(childrenList);
}

Case2:查詢節點數據

@Test
public void testGetData() throws Exception {byte[] bytes = client.getData().forPath("/app2");System.out.println("data: " + new String(bytes));
}

Case3:查詢節點詳細信息

@Test
public void testGetData3() throws Exception {Stat stat = new Stat();client.getData().storingStatIn(stat).forPath("/app2");System.out.println(stat);
}
2.3.2.5 修改節點

修改節點有如下常見的兩種方式:
Case1:修改節點數據

@Test
public void testSetData() throws Exception {Stat stat = client.setData().forPath("/app1", "some data".getBytes());System.out.println(stat);
}

Case2:修改節點數據(帶有版本號)

@Test
public void testSetData2() throws Exception {Stat stat = new Stat();client.getData().storingStatIn(stat).forPath("/app2");int version = stat.getVersion();System.out.println(version);client.setData().withVersion(version).forPath("/app2", "set with version".getBytes());
}

3. ZooKeeper的事件監聽機制

Watcher事件監聽機制:

  • ZooKeeper允許用戶在指定節點上注冊一些Watcher,當一些特定事件發生時,ZooKeeper就會將事件通知給對其感興趣的客戶端,這是ZooKeeper提供分布式協調服務的重要特性
  • ZooKeeper引入了Watcher機制來實現發布 / 訂閱功能,能夠讓多個訂閱者同時監聽某一個對象,當一個對象狀態發生變化時就會通知所有訂閱者
  • ZooKeeper提供原生Watcher的方式,但是比較麻煩,因此Curator使用Cache數據結構進行了優化實現監聽機制
  • Curator提供了如下三種Cache:
    1. NodeCache:只監聽某一個指定的節點變化
    2. PathChildrenCache:監控一個節點的所有子節點
    3. TreeCache:監控整個樹上的節點,類似于前兩者的組合

3.1 Node Cache

代碼實現:

@Test
public void testCuratorCache() throws Exception {NodeCache cache = new NodeCache(client, "/app1");cache.getListenable().addListener(new NodeCacheListener() {@Overridepublic void nodeChanged() throws Exception {System.out.println("監聽到節點變化...");}});cache.start();while (true) {}
}

3.2 PathChildren Cache

代碼實現:

@Test
public void testPathChildrenCache() throws Exception {PathChildrenCache cache = new PathChildrenCache(client, "/app1", true);cache.getListenable().addListener(new PathChildrenCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {System.out.println("監聽到子節點變化...");PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {System.out.println("監聽到子節點數據變化...");System.out.println("更新后數據: " + pathChildrenCacheEvent.getData().getData());}}});cache.start();while (true) {}
}

3.3 Tree Cache

代碼實現:

 @Testpublic void testTreeCache() throws Exception {TreeCache cache = new TreeCache(client, "/app1");cache.getListenable().addListener(new TreeCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {System.out.println("監聽到節點發生變化...");System.out.println(treeCacheEvent);}});cache.start();while (true) {}}

4. ZooKeeper分布式鎖

4.1 ZooKeeper分布式鎖原理

  • 核心思想:當用戶獲取到鎖時就創建節點,使用完鎖就刪除節點
  1. 每當一個用戶想要獲取鎖時就在/lock節點下創建一個 **臨時順序 **節點
  2. 然后獲取/lock節點下的全部子節點,如果發現當前節點編號是最小的,則該節點對應的客戶端獲取到鎖,使用完鎖后,刪除該節點
  3. 如果發現節點編號不是最小的,則對前一個比自己小的編號節點,并注冊事件監聽器,監聽刪除事件
  4. 如果后續發現比自己小的節點被刪除,則客戶端會接收到來自ZooKeeper的通知,然后再次判斷所對應節點編號是否是最小的,重復上述步驟

注意:這里創建臨時節點是因為防止獲取到鎖的客戶端宕機了,進而導致鎖永遠不會被刪的情況;這是創建順序節點是方便編號的排序

Cutator提供了下面五種分布式鎖的方式:

  • InterProcessMutex(分布式可重入排他鎖)
  • InterProcessSemaphoreMutex(分布式不可重入排他鎖)
  • InterProcessReadWriteLock(分布式讀寫鎖)
  • InterProcessMutliLock(將多個鎖作為單個實體管理的容器)
  • InterProcessSemaphoreV2(共享信號量)

4.2 分布式鎖實戰(模擬12306搶票)

代碼如下:

package org.example;import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;import java.util.concurrent.TimeUnit;public class ZooKeeperLockTest {private static int tickets = 10; // 票數public static void main(String[] args) {// 建立連接CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181").sessionTimeoutMs(3000).connectionTimeoutMs(3000).retryPolicy(new ExponentialBackoffRetry(3000, 1)).namespace("").build();client.start();// 獲取分布式鎖InterProcessMutex lock = new InterProcessMutex(client, "/lock");Thread t1 = new Thread(() -> {while (true) {try {boolean hasLock = lock.acquire(3, TimeUnit.SECONDS);if (hasLock && tickets > 0) {// 不斷搶票System.out.println("線程" + Thread.currentThread().getName() + "搶到了當前第" + tickets + "張票");tickets--;if (tickets <= 0) {break;}}} catch (Exception e) {throw new RuntimeException(e);} finally {try {lock.release();} catch (Exception e) {throw new RuntimeException(e);}}}}, "攜程");Thread t2 = new Thread(() -> {while (true) {try {boolean hasLock = lock.acquire(3, TimeUnit.SECONDS);if (hasLock && tickets > 0) {// 不斷搶票System.out.println("線程" + Thread.currentThread().getName() + "搶到了當前第" + tickets + "張票");tickets--;if (tickets <= 0) {break;}}} catch (Exception e) {throw new RuntimeException(e);} finally {try {lock.release();} catch (Exception e) {throw new RuntimeException(e);}}}}, "飛豬");t1.start();t2.start();}
}

5. ZooKeeper集群管理

Leader選舉過程:

  • ServerId:服務器ID

比如有三臺服務器,編號分別是1,2,3。則編號越大在選擇算法中的權重就越大

  • Zxid:數據ID

服務器中存放的數據ID越大,值越大說明更新的越頻繁,則在選擇算法中的權重就越大

  • 在Leader選舉的過程中如果某臺ZooKeeper超過了半數選票,則直接當選為Leader

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

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

相關文章

AR0132AT 1/3 英寸 CMOS 數字圖像傳感器可提供百萬像素 HDR 圖像處理(器件編號包含:AR0132AT6R、AR0132AT6C)

AR0132AT 1/3 英寸 CMOS 數字圖像傳感器&#xff0c;帶 1280H x 960V 有效像素陣列。它能在線性或高動態模式下捕捉圖像&#xff0c;且帶有卷簾快門讀取。它包含了多種復雜的攝像功能&#xff0c;如自動曝光控制、開窗&#xff0c;以及視頻和單幀模式。它適用于低光度和高動態范…

QML界面控件加載與顯示順序

一、QML界面控件加載順序 QML在界面加載時的順序和我們認知的有很大的不同&#xff0c;有時候會對我們獲取參數以及界面實現造成很大的困擾 1、加載順序 import QtQuick 2.12 import QtQml 2.12 import QtQuick.Window 2.12 import QtQuick.VirtualKeyboard 2.4Window {id: …

Open3D點云算法與點云深度學習案例匯總(長期更新)

目錄 引言 Open3D算法匯總 Open3D快速安裝 測試點云資料 一、點云的讀寫與顯示 二、KD tree和八叉樹的應用 三、點云特征提取 四、點云濾波算法 五、點云配準算法 六、點云分割算法&#xff08;待更新&#xff09; 七、常用操作 八、數據轉換 九、常用小工具 三維…

交換機的二三層原理

相同VLAN的交換機交換原理&#xff08;二層交換原理&#xff09;&#xff1a; 交換機收到數據幀&#xff0c;首先會檢查數據幀的VLAN標簽和目標MAC&#xff0c;若屬于相同VLAN&#xff0c;且該目標MAC在本地MAC表中&#xff0c;則直接根據出接口進行數據轉發 不同VLAN的交換機…

九盾安防:如何調控叉車限速器的報警速度呢

在繁忙的物流倉儲和制造業環境中&#xff0c;叉車是不可或缺的搬運設備。然而&#xff0c;其高速行駛也帶來了潛在的安全隱患。為了確保作業人員和貨物的安全&#xff0c;又車限速器的設置顯得尤為關鍵。那么&#xff0c;如何調控叉車限速器的報警速度呢? 叉車限速器的速度調整…

復制vmware虛擬機文件并改名(文件名使用python替換)得到一臺新的虛擬機

文章目錄 需求實驗復制文件夾并重命名使用python將所有文件名“WinSer2022”字符替換成“wingetmac”修改虛擬機配置文件&#xff08;.vmx&#xff09;打開新的虛擬機成功 需求 將已有的Winser2022虛擬機復制成wingetmac并開機 實驗 復制文件夾并重命名 將"WinSer2022…

《人生苦短,我用python·九》python之線程池ThreadPoolExecutor的使用

Python線程池是一種管理和使用線程的高級抽象&#xff0c;使得線程的創建、分配和管理更加方便。通過線程池&#xff0c;可以避免頻繁地創建和銷毀線程&#xff0c;從而提高程序的性能。Python的concurrent.futures模塊提供了一個ThreadPoolExecutor類&#xff0c;可以方便地使…

了解并緩解 IP 欺騙攻擊

欺騙是黑客用來未經授權訪問計算機或網絡的一種網絡攻擊&#xff0c;IP 欺騙是其他欺騙方法中最常見的欺騙類型。通過 IP 欺騙&#xff0c;攻擊者可以隱藏 IP 數據包的真實來源&#xff0c;使攻擊來源難以知曉。一旦訪問網絡或設備/主機&#xff0c;網絡犯罪分子通常會挖掘其中…

1559. 二維網格圖中探測環

1559. 二維網格圖中探測環 給你一個二維字符網格數組 grid &#xff0c;大小為 m x n &#xff0c;你需要檢查 grid 中是否存在 相同值 形成的環。 一個環是一條開始和結束于同一個格子的長度 大于等于 4 的路徑。對于一個給定的格子&#xff0c;你可以移動到它上、下、左、右…

【Qt 初識】QPushButton 的詳解以及 Qt 中的坐標

文章目錄 1. Qt 中的信號槽機制 &#x1f34e;2. 通過圖形化界面的方式實現 &#x1f34e;3. 通過純代碼的方式實現按鈕版的HelloWorld &#x1f34e;4. 設置坐標 &#x1f34e; 1. Qt 中的信號槽機制 &#x1f34e; 》&#x1f427; 本質就是給按鈕的點擊操作&#xff0c;關聯…

C++之復合資料型態 第一部(參考 列舉 指標)

復合資料型態(compound type) 是由其他資料型態(data type) 定義出來的型態&#xff0c; C 中的復合資料型態包括參考(reference) 、列舉(enumeration) 、陣列(array) 、指標(pointer ) 、結構(structure) 及聯合(union) 。 參考 參考是變數(variable) 的別名(alias) &#x…

GuLi商城-商品服務-API-品牌管理-OSS獲取服務端簽名(續)

如何進行服務端簽名直傳_對象存儲(OSS)-阿里云幫助中心 gulimall-third-party服務的代碼: package com.nanjing.gulimall.thirdparty.controller;import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.common.utils.BinaryUtil; impor…

Linux開發:Fuse介紹

Fuse(filesystem in userspace),是一個用戶空間的文件系統。通過fuse內核模塊的支持&#xff0c;開發者只需要根據fuse提供的接口實現具體的文件操作時所對應的回調函數&#xff0c;就可以實現一個文件系統。由于其主要實現代碼位于用戶空間中&#xff0c;因此不需要重新編譯內…

實時數倉項目需求及架構設計

第2章實時數倉項目需求及架構設計 2.1 項目需求分析 1&#xff09;采集平臺 ? &#xff08;1&#xff09;用戶行為數據采集平臺搭建 ? &#xff08;2&#xff09;業務數據采集平臺搭建 2&#xff09;離線需求 … 2.2 項目框架 2.2.1 技術選型 ? 技術選型主要因素&a…

15 - matlab m_map地學繪圖工具基礎函數 - 一些數據轉換函數(二)

15 - matlab m_map地學繪圖工具基礎函數 - 一些數據轉換函數&#xff08;二&#xff09; 0. 引言1. 關于m_geodesic2. 關于mygrid_sand23. 結語 0. 引言 通過前面篇節已經將m_map繪圖工具中大多繪圖有關的函數進行過介紹&#xff0c;已經能夠滿足基本的繪圖需求&#xff0c;本節…

探索 `DatagramSocket` 類

DatagramSocket 類是 Java 網絡編程中的一個關鍵組件&#xff0c;專門用于處理 UDP&#xff08;用戶數據報協議&#xff09;通信。與基于連接的 TCP 不同&#xff0c;UDP 是一種無連接協議&#xff0c;適用于對速度和效率要求較高&#xff0c;但對可靠性要求相對較低的場景。 …

【JavaScript】包裝類

包裝類 JS 提供了三個主要的包裝類&#xff1a;String、Number、Boolean。如果嘗試把原始類型&#xff08;string、number、boolean&#xff09;數據當成對象使用&#xff0c;JS 會自動將其轉換為對應包裝類的實例。 我們先來看一下 “基本類型數據” 及 “其包裝類的實例” …

個人倒計時頁面源碼,實用倒計時單頁源碼

一、源碼描述 這是一款非常實用的個人倒計時頁面&#xff0c;支持設置未來一年時間&#xff0c;支持設置背景音樂&#xff0c;支持自定義下拉頁面&#xff0c;點擊向下箭頭查看。 二、源碼截圖 三、源碼下載

docker 常用命令,后面不斷更新

1.從Docker容器中下載文件到本地的方法 使用 docker cp 命令:該命令可以將文件或目錄從容器復制到主機。該方法簡單快捷&#xff0c;適用于少量文件的下載。 # 將容器名為my_container中的 /data/file.txt文件復制到本地/path/to/save/file.txt docker cp my_container:/data/…

深入探討【C++容器適配器】:現代編程中的【Stack與Queue】的實現

目錄 一、Stack&#xff08;棧&#xff09; 1.1 Stack的介紹 1.2 Stack的使用 1.3 Stack的模擬實現 二、Queue&#xff08;隊列&#xff09; 2.1 Queue的介紹 2.2 Queue的使用 2.3 Queue的模擬實現 三、容器適配器 3.1 什么是適配器 3.2 為什么選擇deque作為stack和…