轉自:http://support.huawei.com/ecommunity/bbs/10242721.html
Zookeeper在HBase中的應用
HBase部署相對是一個較大的動作,其依賴於zookeeper cluster,hadoop HDFS。

Zookeeper作用在於:
1、hbase regionserver 向zookeeper注冊,提供hbase regionserver狀態信息(是否在線)。
2、hmaster啟動時候會將hbase系統表-ROOT- 加載到 zookeeper cluster,通過zookeeper cluster可以獲取當前系統表.META.的存儲所對應的regionserver信息。
zookeeper是hbase集群的"協調器"。由於zookeeper的輕量級特性,因此我們可以將多個hbase集群共用一個zookeeper集群,以節約大量的服務器。多個hbase集群共用zookeeper集群的方法是使用同一組ip,修改不同hbase集群的"zookeeper.znode.parent"屬性,讓它們使用不同的根目錄。比如cluster1使用/hbase-c1,cluster2使用/hbase-c2,等等。
HMaster主要作用在於,通過HMaster維護系統表-ROOT-,.META.,記錄regionserver所對應region變化信息。此外還負責監控處理當前hbase cluster中regionserver狀態變化信息。
hbase regionserver則用於多個/單個維護region。
region則對應為hbase數據表的表分區數據維護。
參考:http://koven2049.iteye.com/blog/1150484
hbase.zookeeper.zookeeperwatcher.java 類
ZooKeeper Watcher. One instance of this is instantiated for each Master, RegionServer, and client process. 每一個Master、RS和客戶端進程都會創建一個zookeeperwatcher的實例。
1、初始化ZooKeeper連接和watcher
① 設置節點名稱
② ZKUtil.connet
③ 如果連接成功,則新建一些節點,如ZKUtil.createAndFailSilent(this, baseZNode); 如果節點存在,則不再創建。不加watch。此處創建的是持久性節點,並具有open access性。
HBase中的znode
/hbase baseZNode
| Node name (fault) |
節點分類 |
|
ZookeeperWatcher初始化時創建 |
| /hbase |
baseZNode |
集群的根znode |
√ |
| /hbase/root-region-server |
rootServerZNode |
包含-ROOT- region的服務器位置的節點 |
|
| /hbase/rs |
rsZNode |
RS的臨時節點 |
√ |
| /hbase/draining |
drainingZNode |
draining RS 臨時節點 |
√ |
| /hbase/master |
masterAddressZNode |
currently active master |
在hbase.master.Hmaster中創建 |
| /hbase/backup-masters |
backupMasterAddressesZNode |
backup master directory, if not the active master |
√ |
| /hbase/shutdown |
clusterStateZNode |
znode containing the current cluster state |
|
| /hbase/unassigned |
assignmentZNode |
region transitioning and assignment |
√在rs啟動時會創建該節點的子節點。ZKAssign會操作此節點,並創建子節點來指示rs的狀態。 |
| /hbase/table |
tableZNode |
table disabling/enabling |
√ |
| /hbase/hbaseid |
clusterIdZNode |
containing the unique cluster ID |
|
| /hbase/splitlog |
splitLogZNode |
log splitting work assignment |
√ |
ZooKeeperWatcher的構造函數的作用就是初始化一個ZooKeeper連接並設置watcher。因此在ZookeeperWatcher初始化時創建的節點,表示只要HBase在連接ZooKeeper時就會創建這些節點。
1、 /hbase的子節點:
![]()
2、 HBase中的list命令和/hbase/table下的子節點對比:前者不包括-ROOT-和.META.表:

3、 啟動HBase時,/hbase/unassigned節點的變化:

ZooKeeperListener.java
package org.apache.hadoop.hbase.zookeeper;
抽象類,實現HBase內部ZooKeeper事件的監聽。ZooKeeperWatcher會執行適當的方法來實現該類。為了從watcher接收到事件,每個監聽者必須要通過ZooKeeperWatcher注冊。子類需要重寫需要的方法。值得注意的是監聽者的watcher在執行這些方法時會引起阻塞,因此不能長期運行這些方法。
在構造函數中就初始化了一個ZooKeeperWatcher。
監聽的事件包括nodeCreated(String path)、nodeDeleted(String path)、nodeDataChanged(String path)、nodeChildrenChanged(String path)。
ActiveMasterManager.java
作用:處理所有master方面的master選舉的事務。監聽並回應master znode的zookeeper通知,包括nodeCreated(節點創建)和nodeDeleted(節點刪除)。
包含阻斷方法,備master等待主master失敗。?
在HMaster構造函數的blockUntilBecomingActiveMaster方法中實例化該類。
實現了抽象類ZooKeeperListener中的nodeCreated(節點創建)和nodeDeleted(節點刪除)方法。
HBase中使用zookeeper的場景(未完)
1、主備master切換時
| 應用場景 |
使用類 |
調用函數 |
備注 |
|||
| Master啟動 |
HMaster |
HMaster(構造函數) |
連接zookeeper |
|||
| 主備master切換 |
HMaster |
becomeActiveMaster(MonitoredTask startupStatus) |
注冊一個Listener |
|||
|
|
HConnectionImplementation |
|
(見hbase.zookeeper源碼-Bene.xlsx中的sheet2)
Zookeeper交流遺留問題
1、Follower和Observer能否寫數據,二者主要區別是什么?
ObserverRequestProcessor會將收到的任何修改狀態的請求都發送給leader。遇到以下操作時,observer和follower都會發送請求給leader
switch (request.type) {
case OpCode.sync:
zks.pendingSyncs.add(request);
zks.getFollower().request(request);
// zks.getObserver().request(request);
break;
case OpCode.create:
case OpCode.delete:
case OpCode.setData:
case OpCode.setACL:
case OpCode.createSession:
case OpCode.closeSession:
case OpCode.multi:
zks.getFollower().request(request);
// zks.getObserver().request(request);
主要區別:Observer不參與leader選舉和投票。
Follower可以寫數據,Observer在客戶端寫數據時不參與,主要通過sync操作更新數據。
二者的主要區別是Follower參與選舉和投票,Observer不參與選舉和投票。
投票在寫數據過程中的作用:客戶端發送寫數據操作時,follower或者Observer將寫數據請求轉發給leader,然后leader發送給具有投票權(也就是follower和leader)的角色;當這些節點有半數以上的節點反饋給leader投票,leader則認為寫數據成功。
observer是zookeeper-3.3版本新添加的一個角色,,他們的引入是為了解決zookeeper集群擴大后,由於網絡可靠性下降可能導致的拜占庭將軍問題。
2、寫數據的原子性如何保證?
ZooKeeper中讀寫數據都具有原子性。
讀數據的原子性是指讀某個節點的數據時,會將該節點所有的數據都返回給客戶端。
寫數據的原子性是指寫數據不會部分失敗或部分成功。一個成功的寫操作必須保證被寫入到大部分zookeeper服務器的永久存儲上(不是上次說的所有服務器)。
3、/hbase/rs節點的子節點是持久節點還是臨時節點?
臨時節點。可以通過在shell腳本查看/hbase/rs節點的數據及其子節點的數據,/hbase/rs是持久節點,其子節點是臨時節點,二者如下圖。
/hbase/rs是持久節點:

這個znode[linux-jay1.jay,20020,1345715787547]是個臨時znode,當該regionserver關閉后,這個znode會消失,那么設置了watcher的master就會第一時間感知到regionserver的退出。

備注:如果是持久節點ephemeralOwner 的值為0。
Get的各個參數解釋:
czxid : The zxid of the change that caused this znode to be created.
mzxid : The zxid of the change that last modified this znode.
ctime : The time in milliseconds from epoch when this znode was created.
mtime : The time in milliseconds from epoch when this znode was last modified.
version : The number of changes to the data of this znode.
cversion : The number of changes to the children of this znode.
aversion : The number of changes to the ACL of this znode
ephemeralOwner : The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero.
dataLength : The length of the data field of this znode.
numChildren : The number of children of this znode.
4、sync操作的作用是什么?
sync操作的作用是使客戶端的znode視圖與ZooKeeper同步,由於讀操作可能會存在連接的某台zookeeper服務器上的數據並不是最新數據,因此zookeeper允許客戶端用sync操作自身更新(如何實現涉及到ZooKeeper內核,目前還沒有看這部分內容)。
5、watcher的設置是一次性的,為什么要如此設計?
Watch是由ZooKeeper服務的操作來設置,同時由服務的其他操作來觸發,watcher只被觸發一次。比如一個客戶端對某個znode調用了exists操作並在這個節點上加了一個Watch,如果該節點不存在,則exists操作返回false。如果一段時間后,這個znode被另外一個客戶端創建了,該Watch將被觸發,通知第一台客戶端znode被創建的消息。
由於是針對操作而設置的,因此很容易區別上次交流時所說的狀態。 ZooKeeper在讀操作exists、getChildren、getData時設置watch,這些操作都由寫操作create、delete和setData來觸發。
如此看來,並不是所有的操作都會觸發watch,也並不是所有的操作都會設置watch。而且通過znode的路徑可以確定是哪個znode發生了改變,通過操作的類型可以確定該節點發生了何種改變。個人認為這樣設置的確增加了通用性,同時也減少了資源消耗。
另外:
ZooKeeper提供配置服務的手段是:用znode的路徑來記錄鍵,用znode的數據來存儲值,因此正好可以使用znode來存儲鍵值對。
比如,/hbase/root-region-server的路徑表示存儲的是-ROOT-表所在服務器的地址,然后用該znode的值來存儲其地址值
