Java操作Zookeeper原理及過(guò)程詳解
ZooKeeper 是一個(gè)典型的分布式數(shù)據(jù)一致性解決方案,分布式應(yīng)用程序可以基于 ZooKeeper 實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負(fù)載均衡、命名服務(wù)、分布式協(xié)調(diào)/通知、集群管理、Master 選舉、分布式鎖和分布式隊(duì)列等功能。
Zookeeper 一個(gè)最常用的使用場(chǎng)景就是用于擔(dān)任服務(wù)生產(chǎn)者和服務(wù)消費(fèi)者的注冊(cè)中心。 服務(wù)生產(chǎn)者將自己提供的服務(wù)注冊(cè)到Zookeeper中心,服務(wù)的消費(fèi)者在進(jìn)行服務(wù)調(diào)用的時(shí)候先到Zookeeper中查找服務(wù),獲取到服務(wù)生產(chǎn)者的詳細(xì)信息之后,再去調(diào)用服務(wù)生產(chǎn)者的內(nèi)容與數(shù)據(jù)。如下圖所示,在 Dubbo架構(gòu)中 Zookeeper 就擔(dān)任了注冊(cè)中心這一角色。
maven依賴(lài)
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.0</version> </dependency>
程序其它依賴(lài):
<!-- Logger(log4j2) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
<!-- Log4j 1.x API Bridge -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.11.2</version>
</dependency>
<!-- SLF4J Bridge -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
API操作代碼:
package com.zhi.test;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
/**
* Zookeeper操作測(cè)試
*
* @author 張遠(yuǎn)志
* @since 2020年5月3日14:31:28
*
*/
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ZookeeperTest {
private final Logger logger = LogManager.getLogger(this.getClass());
private ZooKeeper zooKeeper;
private final String path = "/test";
@BeforeAll
public void init() throws Exception {
zooKeeper = new ZooKeeper("192.168.59.131:2181", 60000, new Watcher() {
public void process(WatchedEvent event) {
logger.info("事件類(lèi)型:{},路徑:{}", event.getType(), event.getPath());
}
});
}
/**
* 添加數(shù)據(jù),當(dāng)路徑已經(jīng)存在時(shí)會(huì)報(bào)錯(cuò),初始版本號(hào)為0。第三個(gè)參數(shù)是權(quán)限控制。 <br>
* 第四個(gè)參數(shù),CreateMode:
* <li>PERSISTENT:持久化保存
* <li>PERSISTENT_SEQUENTIAL:持久化保存,并且路徑附加一個(gè)自動(dòng)增長(zhǎng)的序號(hào)
* <li>EPHEMERAL:臨時(shí)數(shù)據(jù),客戶端斷開(kāi)連接時(shí)自動(dòng)刪除數(shù)據(jù)(dubbo就是采用這種機(jī)制)
* <li>EPHEMERAL_SEQUENTIAL:客戶端斷開(kāi)連接時(shí)自動(dòng)刪除數(shù)據(jù),并且路徑會(huì)附加一個(gè)自動(dòng)增長(zhǎng)的序號(hào)
* <li>CONTAINER:
* <li>PERSISTENT_WITH_TTL:客戶端斷開(kāi)連接時(shí)自動(dòng)刪除數(shù)據(jù),當(dāng)節(jié)點(diǎn)在指定時(shí)間沒(méi)有被修改且沒(méi)有子目錄時(shí),數(shù)據(jù)會(huì)被刪除
* <li>PERSISTENT_SEQUENTIAL_WITH_TTL:客戶端斷開(kāi)連接時(shí)自動(dòng)刪除數(shù)據(jù),路徑會(huì)附加一個(gè)自動(dòng)增長(zhǎng)的序號(hào),且當(dāng)節(jié)點(diǎn)在指定時(shí)間沒(méi)有被修改且沒(méi)有子目錄時(shí),數(shù)據(jù)會(huì)被刪除
*/
@Order(1)
@Test
public void create() {
try {
String back = zooKeeper.create(path, "這是一個(gè)測(cè)試".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
logger.info("添加一條數(shù)據(jù)成功,實(shí)際路徑:{}", back);
} catch (Exception e) {
logger.error("調(diào)用create出錯(cuò)", e);
}
}
/**
* 判斷路徑是否存在,不存在時(shí)返回null
*/
@Order(2)
@Test
public void exists() {
try {
Stat stat = zooKeeper.exists(path, false);
logger.info("路徑為{}的節(jié)點(diǎn){}存在", path, stat == null ? "不" : "");
} catch (Exception e) {
logger.error("調(diào)用exists出錯(cuò)", e);
}
}
/**
* 查詢(xún)數(shù)據(jù),路徑不存在時(shí)會(huì)報(bào)錯(cuò)
*/
@Order(3)
@Test
public void find() {
try {
byte[] bits = zooKeeper.getData(path, false, new Stat()); // 路徑不存在時(shí)會(huì)報(bào)錯(cuò)
String data = new String(bits);
logger.info("路徑{}查詢(xún)到數(shù)據(jù):{}", path, data);
} catch (Exception e) {
logger.error("調(diào)用getData出錯(cuò)", e);
}
}
/**
* 獲取子目錄,結(jié)果為空時(shí)返回一個(gè)長(zhǎng)度為0的ArrayList
*/
@Order(3)
@Test
public void children() {
try {
List<String> list = zooKeeper.getChildren(path, false);
logger.info("路徑{}的子目錄有:{}", path, String.join("、", list.toArray(new String[0])));
} catch (Exception e) {
logger.error("調(diào)用getChildren出錯(cuò)", e);
}
}
/**
* 修改數(shù)據(jù),路徑不存在時(shí)會(huì)報(bào)錯(cuò),版本號(hào)與存儲(chǔ)中不一致時(shí)也報(bào)錯(cuò)
*/
@Order(4)
@Test
public void udpate() {
try {
Stat stat = zooKeeper.exists(path, false);
if (stat != null) {
stat = zooKeeper.setData(path, "這是一個(gè)修改測(cè)試".getBytes(), stat.getVersion()); // 版本號(hào)為-1時(shí)不做版本校驗(yàn)
logger.info("數(shù)據(jù)修改成功,原版本號(hào):{},新版本號(hào):{}", stat.getAversion(), stat.getVersion());
}
} catch (Exception e) {
logger.error("調(diào)用setData出錯(cuò)", e);
}
}
/**
* 刪除節(jié)點(diǎn),路徑不存在時(shí)報(bào)錯(cuò),版本號(hào)不一致時(shí)也會(huì)報(bào)錯(cuò)
*/
@Order(5)
@Test
public void delete() {
try {
zooKeeper.delete(path, -1); // -1表示不做版本校驗(yàn)
logger.info("根據(jù)path刪除數(shù)據(jù)成功");
} catch (Exception e) {
logger.error("調(diào)用delete出錯(cuò)", e);
}
}
@AfterAll
public void destory() throws Exception {
if (zooKeeper != null) {
zooKeeper.close();
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis圖文并茂講解注解開(kāi)發(fā)一對(duì)一查詢(xún)
這篇文章主要介紹了SpringBoot中Mybatis注解一對(duì)一查詢(xún)的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
JAVA TIMER簡(jiǎn)單用法學(xué)習(xí)
Timer類(lèi)是用來(lái)執(zhí)行任務(wù)的類(lèi),它接受一個(gè)TimerTask做參數(shù)2013-07-07
Java的super關(guān)鍵字與instanceof運(yùn)算符使用方法
這篇文章主要介紹了Java的super關(guān)鍵字與instanceof運(yùn)算符使用方法,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09
alibaba?seata服務(wù)端具體實(shí)現(xiàn)
seata是來(lái)處理分布式服務(wù)之間互相調(diào)用的事務(wù)問(wèn)題,本文重點(diǎn)給大家介紹alibaba-seata實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
Java基礎(chǔ)之反射技術(shù)相關(guān)知識(shí)總結(jié)
今天帶大家復(fù)習(xí)Java基礎(chǔ)知識(shí),文中對(duì)Java反射技術(shù)介紹的非常詳細(xì),對(duì)正在學(xué)習(xí)Java的小伙伴們很有幫助,,需要的朋友可以參考下2021-05-05
30分鐘入門(mén)Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí)
這篇文章主要介紹了30分鐘入門(mén)Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí),詳細(xì)介紹了默認(rèn)方法和接口,有興趣的可以了解一下。2017-04-04
SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)動(dòng)態(tài)管理示例
這篇文章主要為大家介紹了SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)動(dòng)態(tài)管理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Mybatis中mapper.xml實(shí)現(xiàn)熱加載介紹
大家好,本篇文章主要講的是Mybatis中mapper.xml實(shí)現(xiàn)熱加載介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01

