(一) ZooKeeper是什麼?
官方上是這麼介紹的:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.All of these kinds of services are used in some form or another by distributed applications
翻譯過來就是:ZooKeeper 是一個典型的分佈式數據一致性解決方案,它能爲分佈式應用程序提供諸如配置管理、命名服務、分佈式鎖、集羣管理等功能.
1.1. 配置管理
Zookeeper提供了這樣的一種服務:一種集中管理配置的方法,我們在這個集中的地方修改了配置,所有對這個配置感興趣的都可以獲得變更。這樣就省去手動拷貝配置了,還保證了可靠和一致性。
1.2. 名字服務
這個可以簡單理解爲一個電話薄,電話號碼不好記,但是人名好記,要打誰的電話,直接查人名就好了。
分佈式環境下,經常需要對應用/服務進行統一命名,便於識別不同服務;
類似於域名與ip之間對應關係,域名容易記住;
通過名稱來獲取資源或服務的地址,提供者等信息
1.3. 分佈式鎖
碰到分佈二字貌似就難理解了,其實很簡單。單機程序的各個進程需要對互斥資源進行訪問時需要加鎖,那分佈式程序分佈在各個主機上的進程對互斥資源進行訪問時也需要加鎖。很多分佈式系統有多個可服務的窗口,但是在某個時刻只讓一個服務去幹活,當這臺服務出問題的時候鎖釋放,立即fail over到另外的服務。這在很多分佈式系統中都是這麼做,這種設計有一個更好聽的名字叫Leader Election(leader選舉)。舉個通俗點的例子,比如銀行取錢,有多個窗口,但是呢對你來說,只能有一個窗口對你服務,如果正在對你服務的窗口的櫃員突然有急事走了,那咋辦?找大堂經理(zookeeper)!大堂經理指定另外的一個窗口繼續爲你服務!
1.4. 集羣管理
在分佈式的集羣中,經常會由於各種原因,比如硬件故障,軟件故障,網絡問題,有些節點會進進出出。有新的節點加入進來,也有老的節點退出集羣。這個時候,集羣中有些機器(比如Master節點)需要感知到這種變化,然後根據這種變化做出對應的決策。我已經知道HDFS中namenode是通過datanode的心跳機制來實現上述感知的,那麼我們可以先假設Zookeeper其實也是實現了類似心跳機制的功能吧!
簡單來說zookeeper=文件系統+監聽通知機制。
1.5、 文件系統
Zookeeper維護一個類似文件系統的數據結構:
每個子目錄項如 NameService 都被稱作爲 znode(目錄節點),和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在於znode是可以存儲數據的。
有四種類型的znode:
-
PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在
-
PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
-
EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除
-
EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
1.6 監聽通知機制
客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
(二) zookeeper單機模式安裝
2.1 檢查java環境
配置JAVA環境,檢驗環境:java -version
2.2 下載並解壓zookeeper
zookeeper下載路徑:https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/, 一定要下載源碼版本,也就是以-bin.tar.gz結尾的包,不然啓動zookeeper時會Starting zookeeper ... FAILED TO START錯誤
2.3 重命名zoo_sample.cfg
重命名zoo_sample.cfg爲zoo.cfg
2.4 啓動zookeeper
bin/zkServer.sh start
2.5 客戶端鏈接zookeeper
bin/zkCli.sh
(三) zookeeper的簡單使用
ls /: 查看zookeeper內容
creaate /zknode data :創建znode節點
get /zknode: 獲取節點內容
delete /zknode: 刪除節點
(四) 使用java API 連接zookeeper
引入依賴:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.5</version>
</dependency>
創建znode : create /zknode data
啓動zookeeper客戶端程序,代碼如下所示
package com.dy.demo.entiy;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class ZookeeperClientSync implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zKeeper = null;
private static Stat stat = new Stat();
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String path = "/zknode";
zKeeper = new ZooKeeper("localhost:2181", 5000, new ZookeeperClientSync());
// 等待zk連接成功的通知
connectedSemaphore.await();
// 獲取path目錄節點的配置數據,並註冊默認的監聽器
System.out.println(new String(zKeeper.getData(path, true, stat)));
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) { // 連接成功
System.out.println("連接成功");
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {// zk目錄節點數據變換通知事件
try {
System.out.println("配置已修改爲: " + new String(zKeeper.getData(event.getPath(), true, stat)));
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
變更znode節點數據 : set /zknode data1234,客戶端打印
參考:https://blog.csdn.net/java_66666/article/details/81015302