1. 程式人生 > >說說zookeeper【叄】_工作機制和實現原理

說說zookeeper【叄】_工作機制和實現原理

本文簡單說說zookeeper的工作機制。

總體來說,客戶端先和zookeeper伺服器建立起一個TCP長連線(session),之後根據ACL許可權的設定,可在zookeeper伺服器上對目錄和節點(zode)進行操作,同時還可以在節點上註冊watcher事件。下面依次展開說明。

session

客戶端和伺服器之間建立TCP長連線,通過心跳檢測和伺服器保持有效的會話,也能向zookeeper伺服器傳送請求和接收響應,還可以通過該連線接收來自伺服器的watcher事件通知。一個session的建立流程如下:

1.初始化Zookeeper物件;

2.設定會話預設watcher;

3.構造zookeeper伺服器地址列表管理器HostProvider;

4.建立並初始化客戶端網路聯結器ClientCnxn(兩個核心佇列outgoingQueue和pendingQueue);

5.初始化SendThread(客戶端服務端之間所有IO)和EventThread(客戶端事件處理);

6.啟動SendThread和EventThread

7.獲取一個zookeeper伺服器地址;

8.建立TCP連線;

9.構造ConnectRequest請求(通過SendThread放到outgoingQueue);

10.傳送請求(ClientCnxn從outgoingQueue中取出,序列化向服務端傳送);

11.接收服務端響應;

12.處理Response(反序列化獲取sessionID);

13.連線成功;

14.生成SyncConnected-None事件,傳遞給EventThread;

15.查詢watcher,取出步驟2中的watcher放到EventThread佇列中;

16.處理事件;

session有如下4個基本屬性:

sessionID:會話唯一標示;

Timeout:會話超時時間;

Ticktime:下次會話超時時間點(13位long型,相當於當前時間加上TImeout);

isClosing:是否已被關閉;

zookeeper對session採用分桶管理策略,根據下次超時時間點(Ticktime)進行分配。

znode

znode可分為持久節點

臨時節點兩類,同時支援對下一級子節點的建立順序進行維護。

持久節點是一旦被建立,除非主動進行znode移除,否則將一直儲存在zookeeper上。

臨時節點的宣告週期和客戶端會話繫結,一旦客戶端會話失效,那麼客戶端所建立的所有臨時節點都會被移除。


對於每個zonode,zookeeper會為其維護一個stat的資料結構,結構如下:


我們看到stat記錄了znode的三個版本引數,分別為version(znode版本)、cversion(znode子節點的版本)和aversion(znode的acl版本)。在客戶端對znode節點進行修改操作時,zookeeper是用過樂觀鎖來實現版本控制的,即先比對當前版本version和操作的版本是否一致,如不一致則拒接,並丟擲BadVersionException異常。

watcher

watcher(事件監聽器)是zookeeper中的一個重要特性,允許使用者在指定節點上註冊一些watcher,在一些特定事件觸發的時候zookeeper服務端會將事件通知到感興趣的客戶端,該機制是zookeeper實現分散式協調服務的重要特性。

watcher通知狀態和事件型別:


watcher的工作機制,大體上分為三個階段:客戶端註冊watcher、服務端處理watcher和客戶端回撥watcher。客戶端先將watcher物件轉交給ZKWatchManager,並最終儲存到一個Map<String , Set<Watcher>>型別的物件dataWatches中,將資料節點路徑和watcher物件對映起來。事件發生時,服務端會將通知狀態(KeeperState)、事件型別(EventType)以及節點路徑(Path)封裝成一個WatchedEvent物件,然後從watcherTable中取出對應的watcher並刪除,呼叫process()介面觸發watcher。客戶端接收到WatchedEvent物件,反序列化並處理。

需要注意的一點是,watcher事件有一次性的特點。即一旦一個watcher事件觸發,zookeeper就會將其移除,因此開發人員需要注意是watcher需要反覆註冊。不過值得慶幸的是在實際開發中我們不需要直接編寫相關程式碼,zookeeper的兩大客戶端zkClient和curator都已近幫我們實現自動再註冊了。

ACL

acl(Access Control Lists)策略用來進行許可權控制,zookeeper支援如下4種許可權模式

IP:通過IP地址來進行許可權控制;

Digest:通過"username:password"許可權標示來進行許可權控制;

World:對所有使用者開放許可權,可看做特殊的Digest模式"world:anyone";

Super:超級管理員許可權,可對任何許可權控制的節點操作;

其中中定義瞭如下5種許可權

create:建立子節點許可權

read:獲取節點資料和子節點列表許可權

write:更新節點資料許可權

delete:刪除子節點許可權

admin:設定節點acl許可權

TXID

對於來自客戶端的每個更新請求,zookeeper都會分配一個全域性唯一的遞增編號,這個編號反應了所有事務操作的先後順序,這就是txid。

TXID是一個64位的數字,其中低32位可看做是一個簡單的單調遞增的計數器,針對客戶端的每個事務請求,leader伺服器在產生一個新的事務proposal的時候,都會對該計數器進行加1操作;而高32位則代表了leader週期epoch的編號,每當選舉產生一個新的leader伺服器,就會從這個leader伺服器上取出其本地日誌中最大事務proposal的ZXID,並從該ZXID中解析出對應的epoch值,然後再對其進行加1操作,之後就會依次編號作為新的epoch,並將低32位置0來生成新的ZXID。zookeeper通過epoch編號來區分leader週期變化,能有效地避免不同的leader伺服器錯誤使用相同的ZXID編號提出不一樣的事務。