ZooKeeper的學習與應用

 近期大概學習了一下ZooKeeper,自己並無深刻。LGG嘗試着在虛擬機裏面搭了平臺,看了看一些教材,從網上處處看別人的博文並引用之,還請各位大牛們諒解個人剽竊。現總結例如如下。

1. ZooKeeper的學習與應用java

 

1.1. 概述node

 

    ZooKeeperApache在很是多雲計算項目中的一個,與Hadoop密切相關,這樣的狀況致使我一開始以爲ZooKeeper的搭建需要Hadoop項目做爲支持,但是最後發現全然不需要,它是可以單獨執行的一個項目。算法

    在網上看到了一個很是不錯的關於ZooKeeper的介紹: 顧名思義動物園管理員,他是拿來管大象(Hadoop) 、 蜜蜂(Hive) 、 小豬(Pig)  的管理員, Apache Hbase和 Apache Solr 以及LinkedIn sensei  等項目中都採用到了 ZookeeperZooKeeper是一個分佈式的,開放源代碼的分佈式應用程序協調服務,ZooKeeper是以Fast Paxos算法爲基礎,實現同步服務,配置維護和命名服務等分佈式應用。shell

    從介紹可以看出,ZooKeeper更傾向於對大型應用的協同維護管理工做。IBM則給出了IBMZooKeeper的認知: Zookeeper 分佈式服務框架是 Apache Hadoop 的一個子項目,它主要是用來解決分佈式應用中經常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。數據庫

    總之,我以爲它的核心詞就是一個單詞,協調。express

 

1.2. ZooKeeper的特徵apache

 

    在Hadoop權威指南中看到了關於ZooKeeper的一些核心特徵,閱讀以後感受總結的甚是精闢,在這裏引用並總結。緩存

 

1.2.1. 簡易session

    ZooKeeper的最重要核心就是一個精簡文件系統,提供一些簡單的操做以及附加的抽象(好比排序和通知)。數據結構

 

1.2.2. 易表達

    ZooKeeper的原型是一個豐富的集合,它們是一些已建好的塊,可以用來構建大型的協做數據結構和協議,好比:分佈式隊列、分佈式鎖以及一組對等體的選舉。

 

1.2.3. 高可用性

    ZooKeeper執行在一些集羣上,被設計成可用性較高的,所以應用程序可以依賴它。ZooKeeper可以幫助你的系統避免單點故障,從而創建一個可靠的應用程序。

 

1.2.4. 鬆散耦合

    ZooKeeper的交互支持參與者之間並不瞭解對方。好比:ZooKeeper可以被當作一種公共的機制,使得進程彼此不知道對方的存在也可以相互發現並且交互,對等方可能甚至不是同步的。

    這一特色我感受最能體現在集羣的部署啓動過程當中。像Hadoop當把配置文件寫好以後,而後執行啓動腳本,則251241242中做爲集羣的虛擬機是同步啓動的,也就是DataNodeNameNodeTaskTracker,以及JobTracker的啓動並執行時在一次啓動過程當中啓動的,就是執行一次啓動腳本文件,則都啓動起來。但是ZooKeeper的啓動過程卻不是這種。我在251241242部署了ZooKeeper集羣,並進行啓動,則啓動的過程是這種:首先ssh251而後啓動,這時候251的集羣節點啓動起來,但是控制檯一直報錯,大概的含義就是沒有檢測到其它兩個結點。接着分別ssh241242,分別啓動集羣中的剩下的結點,當241啓動起來時,回到251查看,發現報錯的信息下降,意思是僅僅差一個結點。當251241242三臺server的結點全部啓動起來,則三臺的server的控制檯打印出正常的信息。

 

1.2.5. ZooKeeper是一個庫

    ZooKeeper提供了一個開源的、共享的運行存儲,以及通用協做的方法,分擔了每個程序猿寫通用協議的負擔。隨着時間的推移,人們可以添加和改進這個庫來知足本身的需求。

 

1.3. Zookeeper基本知識

 

    在這一小結,我介紹關於ZooKeeper的一些基本理論知識,以便對ZooKeeper有一個基本感性的認識吧,由於學習的時間不長,有些的認識多是比較片面的,以後假設有了更深層次的認識,會補充於以後的月總結中。

 

1.3.1. 層次化的名字空間

    ZooKeeper的整個名字空間的結構是層次化的,和通常的Linux文件系統結構很是類似,一顆很是大的樹。這也就是ZooKeeper的數據結構狀況。名字空間的層次由斜槓/來進行切割,在名稱空間裏面的每一個結點的名字空間惟一由這個結點的路徑來肯定。

3.1 ZooKeeper的層次化名字空間

    每一個節點擁有自身的一些信息,包含:數據、數據長度、建立時間、改動時間等等。從這樣一類既含有數據,又做爲路徑表標示的節點的特色中,可以看出,ZooKeeper的節點既可以被看作是一個文件,又可以被看作是一個文件夾,它同一時候具備兩者的特色。爲了便於表達,從此咱們將使用Znode來表示所討論的ZooKeeper節點。

 

1.3.2. Znode

    Znode維護着數據、ACLaccess control list,訪問控制列表)、時間戳等交換版本等數據結構,它經過對這些數據的管理來讓緩存生效並且令協調更新。每當Znode中的數據更新後它所維護的版本將添加,這很相似於數據庫中計數器時間戳的操做方式。

另外Znode還具備原子性操做的特色:命名空間中,每一個Znode的數據將被原子地讀寫。讀操做將讀取與Znode相關的所有數據,寫操做將替換掉所有的數據。除此以外,每一個節點都有一個訪問控制列表,這個訪問控制列表規定了用戶操做的權限。

    ZooKeeper中相同存在暫時節點。這些節點與session同一時候存在,當session生命週期結束,這些暫時節點也將被刪除。暫時節點在某些場合也發揮着很關鍵的數據。

1.3.3. Watch機制

    Watch機制就和單詞自己的意思同樣,看。看什麼?詳細來說就是某一個或者一些Znode的變化。官方給出的定義:一個Watch事件是一個一次性的觸發器,當被設置了Watch的數據發生了改變的時候,則server將這個改變發送給設置了Watch的client,以便通知它們。

Watch機制主要有下面三個特色:

一次性的觸發器(one-time trigger

    當數據改變的時候,那麼一個Watch事件會產生並且被髮送到client中。但是client僅僅會收到一次這種通知,假設之後這個數據再次發生改變的時候,以前設置Watch的client將不會再次收到改變的通知,因爲Watch機制規定了它是一個一次性的觸發器。

發送給client

    這個代表了Watch的通知事件是從server發送給client的,是異步的,這就代表不一樣的client收到的Watch的時間可能不一樣,但是ZooKeeper有保證:當一個client在看到Watch事件以前是不會看到結點數據的變化的。好比:A=3,此時在上面設置了一次Watch,假設A忽然變成4了,那麼client會先收到Watch事件的通知,而後纔會看到A=4

3被設置Watch的數據

    這代表了一個結點可以變換的不一樣方式。一個Znode變化方式有兩種,結點自己數據的變化以及結點孩子的變化。所以Watch也可以設置爲這個Znode的結點數據,固然也可以設置爲Znode結點孩子。

 

1.3.4. ACL訪問控制列表

    這是另一個和Linux操做系統很類似的地方,ZooKeeper使用ACL來控制對旗下Znode結點們的訪問。ACL的實現和Linux文件系統的訪問權限十分相似:它經過設置權限爲來代表是否贊成對一個結點的相關內容的改變。

    但是與傳統Linux機制不太一樣,一個結點的數據沒有相似「擁有者,組用戶,其它用戶」的概念,在ZooKeeper中,ACL經過設置ID以及與其關聯的權限來完畢訪問控制的。ACL的權限組成語法是:

(scheme:expression, perms)

前者代表設置的ID,逗號後面表示的是ID相關的權限,好比:

 (ip:172.16.16.1, READ)

指明瞭IP地址爲如上的用戶的權限爲僅僅讀。

 

下面列舉下面ACL所具備的權限

CREATE:代表你可以建立一個Znode的子結點。

READ:你可以獲得這個結點的數據以及列舉該結點的子結點狀況。

WRITE:設置一個結點的數據。

DELETE:可以刪除一個結點

ADMIN:對一個結點設置權限。

 

1.4. ZooKeeper的部署以及簡單使用

 

    要想使用ZooKeeper,首先就要把它部署在server上跑起來,就想ApacheTomcatFtpServer等server同樣。ZooKeeper的部署方式主要有三種,單機模式、僞集羣模式、集羣模式。事實上剩下的兩種模式都是集羣模式的特殊狀況。

 

1.4.1. 主要的環境變量配置

    Java大型的項目中,環境變量的配置很是重要,假設沒有很是好的配置環境變量的話,甚至項目連啓動都是難事。

export ZOOKEEPER_HOME=/home/zookeeper-3.3.3

export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf

 

    1.4.2. ZooKeeper的單機模式部署

ZooKeeper的單機模式通常是用來高速測試client應用程序的,在實際過程當中不多是單機模式。單機模式的配置也比較簡單。

編寫配置文件zoo.cfg

    zookeeper-3.3.3/conf目錄如下就是要編寫配置文件的位置了。在目錄如下新建一個文件zoo.cfgZooKeeper的執行默認是讀取zoo.cfg文件中面的內容的。如下是一個最簡單的配置文件的例子:

tickTime=2000

dataDir=/var/zookeeper

clientPort=2181

    在這個文件裏,咱們需要指定 dataDir 的值,它指向了一個文件夾,這個文件夾在開始的時候需要爲空。如下是每個參數的含義:

tickTime :基本事件單元,以毫秒爲單位。這個時間是做爲 Zookeeper server之間或client與server之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。 

dataDir :存儲內存中數據庫快照的位置,顧名思義就是 Zookeeper 保存數據的文件夾,默認狀況下,Zookeeper 將寫數據的日誌文件也保存在這個文件夾裏。 

clientPort :這個port就是client鏈接 Zookeeper server的port,Zookeeper 會監聽這個port,接受client的訪問請求。

    使用單機模式時用戶需要注意:這樣的配置方式下沒有 ZooKeeper 副本,因此假設 ZooKeeper server出現問題, ZooKeeper 服務將會中止。

執行執行腳本

    在zookeeper-3.3.3/bin目錄如下執行zkServer.sh就能夠,執行完成以後則ZooKeeper服務變啓動起來。

./zkServer.sh start

    腳本默認調用zoo.cfg裏面的配置,所以程序正常啓動。

 

1.4.3. ZooKeeper的集羣模式部署

    ZooKeeper的集羣模式下,多個Zookeeperserver在工做前會選舉出一個Leader,在接下來的工做中這個被選舉出來的Leader死了,而剩下的Zookeeperserver會知道這個Leader死掉了,在活着的Zookeeper集羣中會繼續選出一個Leader,選舉出Leader的目的是爲了可以在分佈式的環境中保證數據的一致性。如圖所看到的:

3.2 ZooKeeper集羣模式圖

確認集羣server的數量

    由於ZooKeeper集羣中,會有一個Leader負責管理和協調其它集羣server,所以server的數量一般都是單數,好比357...等,這樣2n+1的數量的server就可以贊成最多n臺server的失效。

編寫配置文件

配置文件需要在每臺server中都要編寫,下面是一個配置文件的樣本:

# Filename zoo.cfg

tickTime=2000

dataDir=/var/zookeeper/

clientPort=2181

initLimit=5

syncLimit=2

server.1=202.115.36.251:2888:3888

server.2=202.115.36.241:2888:3888

server.3=202.115.36.242:2888:3888

    initLimit:這個配置項是用來配置 Zookeeper 接受client(這裏所說的client不是用戶鏈接 Zookeeper server的client,而是 Zookeeper server集羣中鏈接到 Leader 的 Follower server)初始化鏈接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper server尚未收到client的返回信息,那麼代表這個client鏈接失敗。總的時間長度就是 5*2000=10 

    syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒 

    server.A=BCD:當中 是一個數字,表示這個是第幾號server;是這個server的 ip 地址;表示的是這個server與集羣中的 Leader server交換信息的port;表示的是萬一集羣中的 Leader server掛了,需要一個port來又一次進行選舉,選出一個新的 Leader,而這個port就是用來運行選舉時server相互通訊的port。假設是僞集羣的配置方式,由於 都是同樣,因此不一樣的 Zookeeper 實例通訊port號不能同樣,因此要給它們分配不一樣的port號。

建立myid文件

    除了改動 zoo.cfg 配置文件,集羣模式下還要配置一個文件 myid,這個文件在 dataDir 文件夾下,這個文件中面就僅僅有一個數據就是 的值,Zookeeper 啓動時會讀取這個文件,拿到裏面的數據與 zoo.cfg 裏面的配置信息比較從而推斷到底是那個 server

執行執行腳本

    和單機模式下的執行方式基本一樣,值得注意的地方就是要分別在不一樣server上執行一次,好比分別在251241242上執行:

./zkServer.sh start

這樣才幹使得整個集羣啓動起來。

 

1.4.4. ZooKeeper的集羣僞分佈

    事實上在企業中式不會存在的,另外爲了測試一個client程序也沒有必要存在,僅僅有在物質條件比較匱乏的條件下才會存在的模式。

集羣僞分佈模式就是在單機下模擬集羣的ZooKeeper服務,在一臺機器上面有多個ZooKeeperJVM同一時候執行。

確認集羣僞server的數量

    2n+1,和以前的集羣分佈一樣。

編寫配置文件

    在/conf目錄新建三個配置文件,zoo1.cfgzoo2.cfg以及zoo3.cfg。配置文件分別例如如下編寫:

Zoo1.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_1

clientPort=2181

server.1=localhost:2887:3887

server.2=localhost:2888:3888

server.3=localhost:2889:3889

Zoo2.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_2

clientPort=2182

server.1=localhost:2887:3887

server.2=localhost:2888:3888

server.3=localhost:2889:3889

Zoo3.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/root/hadoop-0.20.2/zookeeper-3.3.1/d_3

clientPort=2183

server.1=localhost:2887:3887

server.2=localhost:2888:3888

server.3=localhost:2889:3889

    由於三個服務都在同一臺電腦上,所以這裏要保證地址的惟一性,所以要特別注意IP地址和port號不要互相沖突,以避免影響程序的正確運行。

建立myid文件

    這個同集羣模式部署,在各自的目錄如下建立。

執行執行腳本

    由於所有的配置文件都在/conf目錄如下,所以要運行三次,而且要加文件名稱的參數,否則會默認運行zoo.cfg這個文件,例如如下:

./zkServer.sh start zoo1.cfg

./zkServer.sh start zoo2.cfg

./zkServer.sh start zoo3.cfg

運行完畢後,將完畢ZooKeeper的集羣僞分佈的啓動。

 

1.4.5. 經過ZooKeeper命令行工具訪問ZooKeeper

    ZooKeeper命令行工具相似於Linuxshell環境,只是功能確定不及shell啦,但是使用它咱們可以簡單的對ZooKeeper進行訪問,數據建立,數據改動等操做。

當啓動 ZooKeeper 服務成功以後,輸入下述命令,鏈接到 ZooKeeper 服務:

zkCli.sh –server 202.115.36.251:2181

鏈接成功後,系統會輸出 ZooKeeper 的相關環境以及配置信息,並在屏幕輸出「 Welcome to ZooKeeper 」等信息。

命令行工具的一些簡單操做例如如下:

)使用 ls 命令來查看當前 ZooKeeper 中所包括的內容:

[zk: 202.115.36.251:2181(CONNECTED) 1] ls /

)建立一個新的 znode ,使用 create /zk myData 。這個命令建立了一個新的 znode 節點「 zk 」以及與它關聯的字符串:

[zk: 202.115.36.251:2181(CONNECTED) 2] create /zk "myData"

)咱們執行 get 命令來確認 znode 是否包括咱們所建立的字符串:

[zk: 202.115.36.251:2181(CONNECTED) 3] get /zk

)如下咱們經過 set 命令來對 zk 所關聯的字符串進行設置:

[zk: 202.115.36.251:2181(CONNECTED) 4] set /zk "zsl"

)如下咱們將剛纔建立的 znode 刪除:

[zk: 202.115.36.251:2181(CONNECTED) 5] delete /zk

 

1.4.6. 使用API來訪問ZooKeeper

    API訪問ZooKeeper纔是client基本的使用手段,經過在client編寫豐富多彩的程序,來達到對ZooKeeper的利用。這裏給出一個簡單的樣例:(深刻的還沒能力給出啊,樣例是從網上找的很是清晰明瞭)

1. import java.io.IOException;

2.

3. import org.apache.zookeeper.CreateMode;

4. import org.apache.zookeeper.KeeperException;

5. import org.apache.zookeeper.Watcher;

6. import org.apache.zookeeper.ZooDefs.Ids;

7. import org.apache.zookeeper.ZooKeeper;

8.

9. public class demo {

10.     // 會話超時時間,設置爲與系統默認時間一致

11.     private static final int SESSION_TIMEOUT=30000;

12.    

13.     // 建立 ZooKeeper 實例

14.     ZooKeeper zk;

15.    

16.     // 建立 Watcher 實例

17.     Watcher wh=new Watcher(){

18.            public void process(org.apache.zookeeper.WatchedEvent event)

19.            {

20.                    System.out.println(event.toString());

21.            }

22.     };

23.    

24.     // 初始化 ZooKeeper 實例

25.     private void createZKInstance() throws IOException

26.     {             

27.            zk=new ZooKeeper("localhost:2181",demo.SESSION_TIMEOUT,this.wh);

28.           

29.     }

30.    

31.     private void ZKOperations() throws IOException,InterruptedException,KeeperException

32.     {

33.            System.out.println("\n1. 建立 ZooKeeper 節點 (znode : zoo2, 數據: myData2 ,權限: OPEN_ACL_UNSAFE ,節點類型: Persistent");

34.            zk.create("/zoo2","myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

35.           

36.            System.out.println("\n2. 查看是否建立成功: ");

37.            System.out.println(new String(zk.getData("/zoo2",false,null)));

38.                           

39.            System.out.println("\n3. 改動節點數據 ");

40.            zk.setData("/zoo2", "shenlan211314".getBytes(), -1);

41.           

42.            System.out.println("\n4. 查看是否改動成功: ");

43.            System.out.println(new String(zk.getData("/zoo2", false, null)));

44.                           

45.            System.out.println("\n5. 刪除節點 ");

46.            zk.delete("/zoo2", -1);

47.           

48.            System.out.println("\n6. 查看節點是否被刪除: ");

49.            System.out.println(" 節點狀態: ["+zk.exists("/zoo2", false)+"]");

50.     }

51.    

52.     private void ZKClose() throws  InterruptedException

53.     {

54.            zk.close();

55.     }

56.    

57.     public static void main(String[] args) throws IOException,InterruptedException,KeeperException {

58.            demo dm=new demo();

59.            dm.createZKInstance( );

60.            dm.ZKOperations();

61.            dm.ZKClose();

62.     }

63.}

    此類包括兩個基本的 ZooKeeper 函數,分別爲 createZKInstance ()和 ZKOperations ()。當中 createZKInstance ()函數負責對 ZooKeeper 實例 zk 進行初始化。 ZooKeeper 類有兩個構造函數,咱們這裏使用  「 ZooKeeper  String connectString,  int sessionTimeout,  Watcher watcher 對其進行初始化。所以,咱們需要提供初始化所需的,鏈接字符串信息,會話超時時間,以及一個 watcher 實例。 17 行到 23 行代碼,是程序所構造的一個 watcher 實例,它能夠輸出所發生的事件。

    ZKOperations ()函數是咱們所定義的對節點的一系列操做。它包含:建立 ZooKeeper 節點( 33 行到 34 行代碼)、查看節點( 36 行到 37 行代碼)、改動節點數據( 39 行到 40 行代碼)、查看改動後節點數據( 42 行到 43 行代碼)、刪除節點( 45 行到 46 行代碼)、查看節點是否存在( 48 行到 49 行代碼)。另外,需要注意的是:在建立節點的時候,需要提供節點的名稱、數據、權限以及節點類型。此外,使用 exists 函數時,假設節點不存在將返回一

 null 值。

 

1.5. 小結

    對於ZooKeeper的認識眼下處在比較淺顯的狀態,瞭解到了主要的服務的部署以及大概ZooKeeper的工做原理。很是多東西都是僅僅懂得皮毛,現在能夠深深地感覺到「僅僅有結合詳細的應用才幹使你對一個東西有較深的瞭解」這句話的深入含義了。

相關文章
相關標籤/搜索