1.zookeeper簡介
1.zookeeper是一個分佈式系統的協調工具,最開始於hadoop,之後被廣泛的應用與各種分佈式應用,例如dubbo,springcloud都能看到zookeeper的身影。
zookeeper的數據存貯以樹形節點存貯,
zookeeper的數據節點的類型有4中
- CreateMode.PERSISTENT :持久節點,一旦創建就保存到硬盤上面
- CreateMode.SEQUENTIAL : 順序持久節點會在 path後面,自動添加一個遞增的10位整數,
- CreateMode.EPHEMERAL :臨時節點,創建以後如果斷開連接則該節點自動刪除
- CreateMode.EPHEMERAL_SEQUENTIAL :順序臨時節點,會在 path後面,自動添加一個遞增的10位整數
臨時節點不能添加子節點。
2.zookeeper的watch
2.1 一次性觸發器
當data發生改變時,一個watch事件被髮送至客戶端,例如:客戶端設置getData("/znode1", true)後,如果/znode1發生改變或者刪除,那麼客戶端就會得到一個/znode1的Watch事件,但是/znode1再次發生變化,那客戶端是無法收到Watch事件的,除非客戶端設置了新的Watch。
2.2 發送至客戶端
Watch事件是異步發送到Client。Zookeeper可以保證客戶端發送過去的更新順序是有序的。例如:某個Znode沒有設置watcher,那麼客戶端對這個Znode設置Watcher發送到集羣之前,該客戶端是感知不到該Znode任何的改變情況的。換個角度來解釋:由於Watch有一次性觸發的特點,所以在服務器端沒有Watcher的情況下,Znode的任何變更就不會通知到客戶端。不過,即使某個Znode設置了Watcher,且在Znode有變化的情況下通知到了客戶端,但是在客戶端接收到這個變化事件,但是還沒有再次設置Watcher之前,如果其他客戶端對該Znode做了修改,這種情況下,Znode第二次的變化客戶端是無法收到通知的。這可能是由於網絡延遲或者是其他因素導致,所以我們使用Zookeeper不能期望能夠監控到節點每次的變化。Zookeeper只能保證最終的一致性,而無法保證強一致性。
3 設置watch的數據內容
有多種方式改變一個node,
Zookeeper維護了兩個Watch列表,一個節點數據Watch列表,另一個是子節點Watch列表。getData()和exists()設置數據Watch,getChildren()設置子節點Watch。兩者選其一,可以讓我們根據不同的返回結果選擇不同的Watch方式,getData()和exists()返回節點的內容,getChildren()返回子節點列表。因此,setData()觸發內容Watch,create()觸發當前節點的內容Watch或者是其父節點的子節點Watch。delete()同時觸發父節點的子節點Watch和data Watch,以及子節點的內容Watch
事件類型 | 觸發的watch操作 |
---|---|
Created event | exists |
Deleted event | exists,getData,getChildren |
Changed event | exists,getData |
Child event | getChildren |
4.java操作zookeeper
引入maven依賴
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
java操作
package com.zk;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.ArrayList;
public class ZKUtils{
private final String DEFAULT_CONNECT_ADDRESS = "127.0.0.1:2181";
private String connectAddress = null;
private static int sessionTimeOut = 50*1000;
//zookeeper連接實例
public ZooKeeper zooKeeper = null;
public ZKUtils() throws IOException {
zooKeeper = new ZooKeeper(DEFAULT_CONNECT_ADDRESS, sessionTimeOut,
new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println(String.format("path:%s,stat:%s",event.getPath(),
event.getState()));
}
});
}
public ZKUtils(String connectAddress) throws IOException {
this.connectAddress = connectAddress;
zooKeeper = new ZooKeeper(connectAddress, sessionTimeOut,
new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println(String.format("path:%s,stat:%s",event.getPath(),
event.getState()));
}
});
}
/**
* 創建節點
* 1. CreateMode.PERSISTENT :持久節點,一旦創建就保存到硬盤上面
* 2. CreateMode.SEQUENTIAL : 順序持久節點會在 path後面
* 3. CreateMode.EPHEMERAL :臨時節點,創建以後如果斷開連接則該節點自動刪除
* 4. CreateMode.EPHEMERAL_SEQUENTIAL :順序臨時節點
* @param path
* @param data
* @param mode
* @return
* @throws KeeperException
* @throws InterruptedException
*/
public String createZkNode(String path, byte[] data, CreateMode mode) throws KeeperException, InterruptedException {
ArrayList<ACL> acls = ZooDefs.Ids.OPEN_ACL_UNSAFE;
return zooKeeper.create(path,data,acls,mode);
}
public byte[] getZKNodeData(String path) throws KeeperException, InterruptedException {
return zooKeeper.getData(path,true,new Stat());
}
}
官網文檔
https://zookeeper.apache.org/doc/current/zookeeperProgrammers.html#Ephemeral+Nodes