閱讀715 返回首頁    go 阿裏雲 go 技術社區[雲棲]


聊聊Zookeeper-快速開始

什麼是Zookeeper

Zookeeper是一個高性能的分布式應用協調服務的框架。Zookeeper=Zoo+keeper,中文直譯是動物園的看守者。

為什麼要使用Zookeeper

Zookeeper可以用於解決很多分布式係統遇到的問題,比如分布式鎖,分布式協調,分布式消息隊列等。

安裝Zookeeper

在官網下載最新的Zookeeper穩定版,https://zookeeper.apache.org/releases.html#download,將下載的文件存放在本地目錄及安裝完畢,本文將Zookeeper安裝在/Developer/java/project目錄。本文下載的是zookeeper-3.4.9版本。

單機模式啟動Zookeeper

下載完之後,將conf目錄下的zoo_sample.cfg文件重命名成zoo.cfg文件。這個文件存放著Zookeeper的所有配置信息。

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
clientPort=2181
maxClientCnxns=60
autopurge.snapRetainCount=3
autopurge.purgeInterval=1
  • tickTime:客戶端和服務器端維持心跳的時間,單位為毫秒。
  • initLimit:
  • syncLimit:
  • dataDir:用來存放快照數據,官方建議不要使用/tmp目錄,可以使用/tmp/zookeeper。
  • clientPort;啟動Zookeeper服務的默認端口。
  • maxClientCnxns:最大客戶端連接數。如果客戶端的數量超過了指定的數量,則新連接的客戶端會拋出java.io.IOException: Connection reset by peer異常。
  • autopurge.snapRetainCount:
  • autopurge.purgeInterval:

通過zkServer.sh start命令啟動Zookeeper,啟動後默認端口是2181,啟動成功後命令行會回顯已經啟動成功的標示STARTED。

tengfeifangtf:bin tengfei.fangtf$ sh /Developer/java/project/zookeeper-3.4.9/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /Developer/java/project/zookeeper-3.4.9/bin/../conf/zoo.cfg
-n Starting zookeeper ...
STARTED

通過命令行調用Zookeeper

連接Zookeeper

通過如下命令連接Zookeeper服務器端。如果服務器端不存在,則會拋出java.net.ConnectException: Connection refused異常

tengfeifangtf:bin tengfei.fangtf$ sh /Developer/java/project/zookeeper-3.4.9/bin/zkCli.sh -server 127.0.0.1:2181
Connecting to 127.0.0.1:2181
2016-09-17 22:02:00,703 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT
2016-09-17 22:02:00,707 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=192.168.100.224
2016-09-17 22:02:00,707 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.6.0_65
2016-09-17 22:02:00,710 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Apple Inc.
2016-09-17 22:02:00,710 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
2016-09-17 22:02:00,710 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/Developer/java/project/zookeeper-3.4.9/bin/../build/classes:/Developer/java/project/zookeeper-3.4.9/bin/../build/lib/*.jar:/Developer/java/project/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/Developer/java/project/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/Developer/java/project/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/Developer/java/project/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/Developer/java/project/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/Developer/java/project/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/Developer/java/project/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/Developer/java/project/zookeeper-3.4.9/bin/../conf:
2016-09-17 22:02:00,711 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
2016-09-17 22:02:00,711 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/var/folders/6s/z6xt4ypn387239k7q1ty_rkc0000gn/T/
2016-09-17 22:02:00,713 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
2016-09-17 22:02:00,713 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Mac OS X
2016-09-17 22:02:00,714 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=x86_64
2016-09-17 22:02:00,714 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=10.11.6
2016-09-17 22:02:00,714 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=tengfei.fangtf
2016-09-17 22:02:00,714 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/Users/tengfei
2016-09-17 22:02:00,714 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/Developer/java/project/zookeeper-3.4.9/bin
2016-09-17 22:02:00,716 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@3a21b220
Welcome to ZooKeeper!
2016-09-17 22:02:00,754 [myid:] - INFO  [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (java.lang.SecurityException: Unable to locate a login configuration)
JLine support is enabled
2016-09-17 22:02:00,775 [myid:] - INFO  [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@876] - Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session
[zk: 127.0.0.1:2181(CONNECTING) 0] 2016-09-17 22:02:01,075 [myid:] - INFO  [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x157386e843d0004, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

連接成功後會進入Zookeeper交互式窗口,命令行左邊顯示如下,然後你就可以使用Zookeeper提供的命令來創建,修改和刪除節點。

[zk: 127.0.0.1:2181(CONNECTED) 0]

創建節點

使用create參數創建節點,第一個參數是節點路徑,第二個參數是節點的數據。

[zk: 127.0.0.1:2181(CONNECTED) 1] create /dmcNode data
Created /dmcNode

注意:節點路徑是大小寫敏感的。

查看節點

使用get命令查詢節點的數據,會顯示節點的數據長度,數據的版本

[zk: 127.0.0.1:2181(CONNECTED) 2] get /dmcNode
data
cZxid = 0x54
ctime = Sat Sep 17 22:07:49 CST 2016
mZxid = 0x54
mtime = Sat Sep 17 22:07:49 CST 2016
pZxid = 0x54
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

通過get命令我們可以看到Zookeeper節點的數據結構

  • cxxid:當前節點事務的xxid。
  • ctime:當前節點的創建時間。
  • mxxid: 當前節點最近修改的xxid。
  • pZxid : 子節點的最後版本
  • cversion:這個節點的子節點變化次數,創建一個子節點會加1。
  • dataVersion:數據的版本,每次修改會加一。
  • aclVersion:這個節點的ACL變化次數。
  • ephemeralOwner :如果這個節點是臨時節點,表示創建者的會話id。如果不是臨時節點,這個值是0。
  • dataLength:這個節點存放的數據長度。
  • numChildren:這個節點的子節點個數。
  • mtime:這個節點的最後修改時間。

這些屬性可以參考《Zookeeper官方文檔》Zookeeper tatStructure章節https://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html#sc_zkStatStructure

修改節點

可以發現dataVersion從剛才的0變成了1,數據長度也變化了。

[zk: 127.0.0.1:2181(CONNECTED) 3] set /dmcNode data1
cZxid = 0x54
ctime = Sat Sep 17 22:07:49 CST 2016
mZxid = 0x55
mtime = Sat Sep 17 22:10:46 CST 2016
pZxid = 0x54
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

刪除節點

通過delete [path]命令刪除節點

[zk: 127.0.0.1:2181(CONNECTED) 12] delete /dmcNode

help命令

我們通過help命令可以看下Zookeeper提供哪些操作命令。

[zk: 127.0.0.1:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
    connect host:port
    get path [watch]
    ls path [watch]
    set path data [version]
    rmr path
    delquota [-n|-b] path
    quit
    printwatches on|off
    create [-s] [-e] path data acl
    stat path [watch]
    close
    ls2 path [watch]
    history
    listquota path
    setAcl path acl
    getAcl path
    sync path
    redo cmdno
    addauth scheme auth
    delete path [version]
    setquota -n|-b val path    
  • quit:退出連接。
  • history:查看當前連接曆史執行命令。

關閉Zookeeper

如果先關閉了Zookeeper服務端,而客戶端沒有關閉,則客戶端會不斷的重連服務器端,並拋出異常closing socket connection and attempting reconnect。

sh /Developer/java/project/zookeeper-3.4.9/bin/zkServer.sh stop

通過Java API調用Zookeeper

1:引入POM

<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.4.7</version>
</dependency>

2:Java測試代碼

演示了ZooKeeper節點的創建,修改和刪除操作。

import java.io.IOException;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;

/**
 * 
 * @author tengfei.fangtf
 * @version $Id: TestZookeeper.java, v 0.1 Sep 14, 2016 5:05:07 PM tengfei.fangtf Exp $
 */
public class TestZookeeper {

    public static void main(String[] args) throws IOException, InterruptedException,
                                           KeeperException {
        //創建ZooKeeper實例
        ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 100, null);
        String path = "/dmc";

        //創建一個節點,模式是PERSISTENT
        zk.create(path, "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("創建節點" + path + ",數據為:" + new String(zk.getData(path, null, null)));
        //修改節點數據
        zk.setData(path, "2".getBytes(), -1);
        System.out.println("修改節點" + path + ",數據為:" + new String(zk.getData(path, null, null)));
        //刪除一個節點
        System.out.println(zk.exists(path, null));
        zk.delete(path, -1);
        //節點是否存在
        System.out.println(zk.exists(path, null));

    }

}

輸出的結果如下:

創建節點/dmc,數據為:1
修改節點/dmc,數據為:2
78,79,1474120607561,1474120607575,1,0,0,0,1,0,78

null

參考資料

最後更新:2017-05-19 14:05:03

  上一篇:go  《HTTP Client官方指南》翻譯邀請
  下一篇:go  穀歌發論文披露TPU詳細信息,比GPU、CPU快15-30倍