概述
ZooKeeper是一個分布式開源框架,提供了協調分布式應用的基本服務,它向外部應用暴露一組通用服務——分布式同步(Distributed Synchronization)、命名服務(Naming Service)、集群維護(Group Maintenance)等,簡化分布式應用協調及其管理的難度,提供高性能的分布式服務。ZooKeeper本身可以以Standalone模式安裝運行,不過它的長處在於通過分布式ZooKeeper集群(一個Leader,多個Follower),基於一定的策略來保證ZooKeeper集群的穩定性和可用性,從而實現分布式應用的可靠性。
本地模式安裝 :本人linux下的JDK版本是1.8
下載地址:https://mirror.bit.edu.cn/apache/ 找到zookeeper 選擇對應版本下載即可。 3.5.5版本開始要下載 bin.tar.gz 的包。
1.下載並解壓 zookeeper-3.4.13.tar.gz
tar -zxvf zookeeper-3.4.13.tar.gz -C /mysoft/
2.修改配置文件
cp zoo_sample.cfg zoo.cfg
修改以下參數。將zookeeper的數據存儲指定到文件夾,創建文件夾 mkdir zkData

3.啟動zookeeper ,停止使用 bin/zkServer.sh stop
bin/zkServer.sh start

查看運行狀態
bin/zkServer.sh status

4.啟動zookeeper客戶端
bin/zkCli.sh
退出使用 quit ,連接其他客戶端 zkCli.sh -serve 127.0.0.1(IP):2182(port) 這樣子來連接

5.zookeeper 配置文件
# The number of milliseconds of each tick # 心跳時間2秒 # 客戶端與服務器或者服務器與服務器之間維持心跳, # 也就是每個tickTime時間就會發送一次心跳。 # 通過心跳不僅能夠用來監聽機器的工作狀態, # 還可以通過心跳來控制Flower跟Leader的通信時間, # 默認情況下FL的會話時常是心跳間隔的兩倍。 tickTime=2000 # The number of ticks that the initial # synchronization phase can take # 集群中的follower服務器(F)與leader服務器(L)之間 # 初始連接時能容忍的最多心跳數(tickTime的數量)。 # tickTime * 10 =20秒沒通訊就認為掛了 initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement # 集群中flower服務器(F)跟leader(L) # 服務器之間的請求和答應最多能容忍的心跳數。 # tickTime * 5 =10秒沒通訊就認為掛了 syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. # 數據存放位置 dataDir=/mysoft/zookeeper-3.4.13/zkData # the port at which the clients will connect # 客戶端連接的接口,客戶端連接zookeeper服務器的端口, # zookeeper會監聽這個端口,接收客戶端的請求訪問!這個端口默認是2181。 clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1
zookeeper 日志的配置地址在conf/目錄下的log4j.properties文件中,該文件中有一個配置為“zookeeper.log.dir=.”,表示log4j日志文件在與執行程序(zkServer.sh)在同一目錄下。當執行zkServer.sh 時,在該文件夾下會產生zookeeper.out日志文件,可以通過日志文件查看運行信息。
偽分布式安裝:
1.解壓完安裝包后,進入zookeeper/conf/目錄下,將改目錄下的zoo_sample.cfg配置文件拷貝3份,依次 zoo1.cfg zoo2.cfg zoo3.cf。使用vim編輯zoo1.cfg zoo2.cfg zoo3.cfg這三個配置文件。
clientPort = ?, 分別將三個配置文件修改為2181.2182.2183 修改dataDir的路徑,分別為zkData1. zkData2. zkData3,並且再對應服務上的zookeeper-3.4.13目錄下創建文件夾 dataDir=/mysoft/zookeeper-3.4.13/zkData 文件結尾添加以下信息,我這里是准備部署3台,所以只有3條信息 server.1=IP:2888(數據同步端口):3888(Leader選舉端口) server.2=IP:2889:3889 server.3=IP:2890:3890
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集群中的 Leader 服務器交換信息的端口;D 表示的是萬一集群中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是偽集群的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
2.在各data文件下創建名為myid的文件,文件內容對應服務器編號
touch myid
3.寫入服務器編號,也就是1中server.1(2.3)的對應值
echo 1 > zkDdata1/myid echo 2 > zkDdata2/myid echo 3 > zkDdata3/myid
4.依次啟動服務,服務按照次序啟動,啟動時的選舉算法是依次投票,這里的leader順理就是2號配置文件啟動的服務。其他的都是fllower,當啟動第一台服務器的時候查看狀態是不可用的,應為集群中節點未在半數以上。 集群中奇數和偶數對故障的容忍度是一致的....所以建議配置奇數個,並不是必須奇數...
sh zkServer.sh start /mysoft/zookeeper-3.4.13/conf/zoo1.cfg sh zkServer.sh start /mysoft/zookeeper-3.4.13/conf/zoo2.cfg sh kServer.sh start /mysoft/zookeeper-3.4.13/conf/zoo3.cfg
5.查看狀態 記得關閉防火牆哦
sh zkServer.sh status /mysoft/zookeeper-3.4.13/conf/zoo1.cfg sh zkServer.sh status /mysoft/zookeeper-3.4.13/conf/zoo2.cfg sh zkServer.sh status /mysoft/zookeeper-3.4.13/conf/zoo3.cfg
啟動客戶端 sh zkCli.sh -server 127.0.0.1:port
偽分布式安裝就是在一台機器上配置多個配置文件,根據不同的配置文件來啟動,而真正的分布式下就是將配置文件安裝在各自服務器下。要注意server的配置

基於 Java API 初探 zookeeper 的使用:
先來簡單看一下API的使用:
public class ConnectionDemo { public static void main(String[] args) { try { final CountDownLatch countDownLatch=new CountDownLatch(1); ZooKeeper zooKeeper= new ZooKeeper("192.168.254.135:2181," + "192.168.254.136:2181,192.168.254.137:2181", 4000, new Watcher() { @Override public void process(WatchedEvent event) { if(Event.KeeperState.SyncConnected==event.getState()){ //如果收到了服務端的響應事件,連接成功 countDownLatch.countDown(); } } }); System.out.println(zooKeeper.getState());//CONNECTING countDownLatch.await(); System.out.println(zooKeeper.getState());//CONNECTED //添加節點 zooKeeper.create("/zk-wuzz","0".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); Thread.sleep(1000); Stat stat=new Stat(); //得到當前節點的值 byte[] bytes=zooKeeper.getData("/zk-wuzz",null,stat); System.out.println(new String(bytes)); // 0 //修改節點值 zooKeeper.setData("/zk-wuzz","1".getBytes(),stat.getVersion()); //得到當前節點的值 byte[] bytes1=zooKeeper.getData("/zk-wuzz",null,stat); System.out.println(new String(bytes1)); // 1 zooKeeper.delete("/zk-wuzz",stat.getVersion()); zooKeeper.close(); System.in.read(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (KeeperException e) { e.printStackTrace(); } } }
