zookeeper基本操作
理解Zookeeper的一種方法是將他視為一個提供高可用性的文件系統。它沒有文件和目錄,但是有一個統一概念的節點,叫做znode,作為數據以及其他znode的容器。znode來自於一個層次級的命名空間。傳統的建立成員列表的方法是以小組的名稱創建一個父znode,同時子znode使用的是組成員的名稱。
1.創建組
下面要寫一個為組創建一個znode的程序,來介紹一下Zookeeper 的Java API。如下:
public class ConnectionManager implements Watcher{ private static final int SESSION_TIMEOUT = 5000; protected ZooKeeper zk; private CountDownLatch countDownLatch = new CountDownLatch(1); public void connect(String hosts) throws IOException, InterruptedException { zk = new ZooKeeper(hosts,SESSION_TIMEOUT,this); countDownLatch.await(); } public void process(WatchedEvent watchedEvent) {if(watchedEvent.getState() == Event.KeeperState.SyncConnected) { countDownLatch.countDown(); } } public void close() throws InterruptedException { zk.close(); } }
public class CreateGroup extends ConnectionManager{ public void createGroup(String groupName) throws KeeperException, InterruptedException { String path= "/" + groupName; String createPath = zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("Create:"+createPath); } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { CreateGroup group = new CreateGroup(); group.connect("localhost"); group.createGroup("/zoo"); group.close(); } }
main方法執行的時候,先創建一個CreateGroup對象,並調用它的connect方法,此方法實例化一個新的zookeeper對象,他是客戶端API的主要類並且維護著客戶端和zookeeper服務端的鏈接。這個構造函數有三個參數,第一個是Zookeeper的主機地址,第二個是每個會話的超時時間,第三個是Watcher對象的實例,Watcher接收Zookeeper的響應,並通知它各種事件,這個例子中ConnectionManager是一個Watcher,因此我們將他傳遞給Zookeeper的構造函數。
當一個zookeeper的實例被創建後,它啟動一個線程鏈接到zookeeper服務。對構造函數的響應返回很快,因此在使用zookeeper對象前等待鏈接建立非常重要。在這裏我們使用Java的CountDownLatch來阻塞,直到zookeeper準備好客戶端鏈接到zookeeper後,Watcher的process方法會被調用,並收到一個事件,表明鏈接已經建立。當收到該事件的時候,我們使用CountDownLatch的countDown操作減掉一個計數。此時計數器歸0,await方法返回。當connect方法完成後,調用createGroup方法。在這個方法裏我們使用zookeeper的create方法創建一個新的zookeeper的node。znode可能是臨時的或則永久性的。一個臨時性的znode,在客戶端與服務端斷開連接後,服務端便把節點刪除。create方法的返回值是ZookEeper的創建路徑。
2加入組
下面是一個將成員註入到組裏的程序,每一個程序在程序運行的時候加入到組中,當程序結束的時候,它必須從這個組中移除。我們可以在Zookeeper的命名空間下創建臨時節點來實現。
public class JoinGroup extends ConnectionManager{ public void joinGroup(String groupName,String memberName) throws KeeperException, InterruptedException { String path = "/" + groupName + "/" + memberName; String createPath = zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("Create:"+createPath); } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { JoinGroup group = new JoinGroup(); group.connect("localhost"); group.joinGroup("/zoo","test"); group.close(); } }
JoinGroup與CreateGroup十分的相似,在joinGroup中創建一個臨時的節點作為znode的子節點,最後會看到在程序結束的時候,臨時節點也相應的被刪除。
3.列出組成員
現在我們實現一個程序,找出組中的成員,實現如下:
public class ListGroup extends ConnectionManager{ public void listGroup(String groupName) throws KeeperException, InterruptedException { String path = "/" + groupName; List<String> children = zk.getChildren(path,false); if(children.isEmpty()){ System.out.println("no child"); System.exit(1); }else{ for(String child : children){ System.out.println(child); } } } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ListGroup group = new ListGroup(); group.connect("localhost"); group.listGroup("/zoo"); group.close(); } }
4.刪除一個組
Zookeeper提供了一個帶有路徑和版本號的delete方法,Zookeeper只在刪除的znode的版本號和已經定義過的版本號一樣的時候才會刪除該znode,樂觀鎖機制能夠使客戶端發現znode修改的沖突,你可以不管版本號而使用版本號-1來刪除該znode。早zookeeper中沒有遞歸刪除操作,因此在刪除父節點前要先刪除子節點信息
public class DeleteGroup extends ConnectionManager{ public void deleteGroup(String groupName) throws KeeperException, InterruptedException { String path = "/" + groupName; List<String> children = zk.getChildren(path,false); for(String child : children){ String tempPath = path + "/" + child; List<String> temp = zk.getChildren(tempPath,false); if(temp.isEmpty()) { zk.delete(path + "/" + child, -1); }else{ deleteGroup(tempPath); } } zk.delete(path,-1); } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { DeleteGroup group = new DeleteGroup(); group.connect("localhost"); group.deleteGroup("/zoo"); group.close(); } }
zookeeper基本操作