1. 程式人生 > >Alex 的 Hadoop 菜鳥教程: 第9課 zookeeper 介紹和使用

Alex 的 Hadoop 菜鳥教程: 第9課 zookeeper 介紹和使用

  • ZooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務。
  • ZooKeeper的目標就是封裝好複雜易出錯的關鍵服務,將簡單易用的介面和效能高效、功能穩定的系統提供給使用者
  • ZooKeeper包含一個簡單的原語集,提供Java和C的介面。
    在Zookeeper中,znode是一個跟Unix檔案系統路徑相似的節點,可以往這個節點儲存或獲取資料。如果在建立znode時Flag設定為EPHEMERAL,那麼當建立這個znode的節點和Zookeeper失去連線後,這個znode將不再存在在Zookeeper裡,Zookeeper使用Watcher察覺事件資訊。當客戶端接收到事件資訊,比如連線超時、節點資料改變、子節點改變,可以呼叫相應的行為來處理資料。Zookeeper的Wiki頁面展示瞭如何使用Zookeeper來處理事件通知,佇列,優先佇列,鎖,共享鎖,可撤銷的共享鎖,兩階段提交。
簡單的說: 通過在zookeeper裡面註冊znode節點,可以做兩件事情
  • 對於分散式服務來說,通過zookeeper可以作為管理節點的一個橋樑,就拿Hbase來說,當你增加一個regionserver的時候根本不需要去master那裡去增加一些配置,你只需要在regionserver上配置好zookeeper的地址,master隔幾秒會去zookeeper上看下,是否有多了regionserver,如果有就自動使用了,master,regionserver都在zookeeper上註冊著,所以jdbc連線也只要去zookeeper上查就可以知道該連哪個master
  • 我們可以自動監控這些節點是否活著,而不用手動去實現這些事情,所以zookeeper解決了使用者想知道節點“是否活著?”的問題

快速開始

安裝

服務端,在每一臺需要監控的機器上安裝

yum install zookeeper-server

客戶端
yum install zookeeper-client

配置

編輯 /etc/zookeeper/conf/zoo.cfg ,所有機器上的 zoo.cfg 這個檔案都是一樣的
maxClientCnxns=50
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=/var/lib/zookeeper
# the port at which the clients will connect
clientPort=2181
server.1=host1:2888:3888
server.2=host2:2888:3888

  • tickTime 單位是毫秒,被用作計算會話超時時間和心跳時間的最小單位,這兩個時間會被表示成 tickTime 的倍數,而不是直接寫上毫秒數,不懂這樣設計的好處在哪裡,不過至少使用者簡單了一點,只需要寫上倍數就行了
  • dataDir 儲存記憶體資料的快照或者關於事務的更新日誌
  • clientPort 給客戶端使用的埠

使用

在所有機器上啟動zookeeper
service zookeeper-server start


使用 zookeeper-client 進入客戶端
[zk: localhost:2181(CONNECTED) 0] 
使用help命令看看有什麼可以用的命令
[zk: localhost: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

我們來試試看最簡單的 ls 命令
[zk: localhost:2181(CONNECTED) 1] ls /
[hadoop-ha, hbase, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /hadoop-ha
[mycluster]


可以看到下面有三個節點,hadoop-ha 下面還有一個節點。這都是因為我之前的教程已經安裝了hadoop和hbase所以會有這些節點。做到這裡,我們明白了,zookeeper維持了一個類似資料夾結構的空間,在這個空間記憶體儲的東西就是znode,znode可以有自己的子節點

建立節點

接下來,我們試試建立一個新的節點
[zk: localhost:2181(CONNECTED) 3] create /zk_test my_data
Created /zk_test
[zk: localhost:2181(CONNECTED) 4] ls /
[hadoop-ha, hbase, zookeeper, zk_test]

這個zk_test 是我們要建立的節點名字,my_data 是節點的資料。 我們可以用get命令看下節點的資料

節點資料

[zk: localhost:2181(CONNECTED) 5] get /zk_test
my_data
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x2200000019
mtime = Sun Jan 18 02:30:56 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

在講解這些引數之前先介紹一下一個概念: ZooKeeper以多種方式跟蹤時間
  • zxid:每次修改ZooKeeper狀態都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小於zxid2,那麼zxid1在zxid2之前發生。
  • 版本號:對節點的每次修改將使得節點的版本號增加一。版本號有三種:version(znode資料修改的次數)、cversion(znode子節點修改的次數),以及aversion(znode的ACL修改次數)。
  • tick:多伺服器ZooKeeper中,伺服器使用tick來定義狀態上傳、會話超時、節點間連線超時等事件的時序。tick僅被最小會話超時(2倍的tick時間)間接使用:如果客戶端要求小於最小會話超時的時間,伺服器將告知客戶端,實際使用的是最小會話超時。
  • 真實時間:除了在建立和修改znode時將時間戳放入stat結構體中之外,ZooKeeper不使用真實時間,或者說時鐘時間。
get獲得的引數的意思是:
  • czxid:建立節點的事務的zxid
  • mzxid:對znode最近修改的zxid
  • ctime:以距離時間原點(epoch)的毫秒數表示的znode建立時間
  • mtime:以距離時間原點(epoch)的毫秒數表示的znode最近修改時間
  • pzxid:子節點的最後版本
  • cversion:znode子節點修改次數
  • dataVersion:資料的版本
  • aclVersion:znode的ACL修改次數
  • ephemeralOwner:如果znode是臨時節點,則指示節點所有者的會話ID;如果不是臨時節點,則為零。
  • dataLength:znode資料長度。
  • numChildren:znode子節點個數。

修改節點

不需要完全看懂以上這些引數,我們可以試著修改一下資料再看
[zk: localhost:2181(CONNECTED) 6] set /zk_test junk
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x220000001a
mtime = Sun Jan 18 02:55:35 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: localhost:2181(CONNECTED) 7] get /zk_test
junk
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x220000001a
mtime = Sun Jan 18 02:55:35 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

再對比一下之前的引數,會發現以下引數改變了
  • mZxid :變為另一個數據,表示最後修改的版本
  • mtime:最後修改時間變了
  • dataVersion:從0變成1,表示資料的版本增加了1
  • dataLength:資料長度變化了

什麼是ACL

    ZooKeeper使用ACL控制對節點的訪問。ACL的實現同Unix檔案訪問許可權非常相似:採用許可權位來定義允許/禁止的各種節點操作,以及位應用的範圍。與標準Unix許可權不同的是,ZooKeeper節點不由使用者(檔案所有者)、組和其他這三個標準範圍來限制。ZooKeeper沒有節點所有者的概念。取而代之的是,ACL指定一個ID集合,以及與這些ID相關聯的許可權。     還要注意的是,ACL僅僅用於某特定節點。特別是,ACL不會應用到子節點。比如說,/app只能被ip:172.16.16.1讀取,/app/status可以被所有使用者讀取。ACL不是遞迴的。ZooKeeper支援可插入式鑑權模式。使用scheme:id的形式指定ID,其中scheme是id對應的鑑權模式。比如說,ip:172.16.16.1是地址為172.16.16.1的主機的ID。     客戶端連線到ZooKeeper,驗證自身的時候,ZooKeeper將所有對應客戶端的ID都關聯到客戶端連線上。客戶端試圖存取節點的時候,ZooKeeper會在節點的ACL中校驗這些ID。ACL由(scheme:expression,perms)對組成。expression的格式是特定於scheme的。比如說,(ip:19.22.0.0/16,READ)給予任何IP地址以19.22開頭的客戶端以READ許可權。
只需要知道概念就行了,具體的使用等需要的時候再學習。

刪除節點

[zk: localhost:2181(CONNECTED) 8] delete /zk_test
[zk: localhost:2181(CONNECTED) 9] ls /
[hadoop-ha, hbase, zookeeper]

可以看到節點被刪除了

總結

     其實這個教程只是讓你知道了zookeeper是如何管理節點的,但是沒有說明zookeeper是如何監聽節點和標記節點的,因為那些有點複雜並且對我們普通開發者其實作用不太大,這些一般是 hadoop或者storm 的開發者需要考慮的問題。我們作為終端使用者只需要對zookeeper是個怎樣的東西,究竟是長什麼樣子有一個感性的認識就可以了。

參考資料

  • http://zookeeper.apache.org/doc/trunk/zookeeperStarted.html
  • http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#sc_zkDataModel_znodes
  • http://blog.163.com/wm_at163/blog/static/132173490201232423051163/