Zookeeper 開發引言翻譯

Zookeeper

概念


1. ZNodes - The Zookeeper Data Model

Zookeeper 有一個類似於分佈式文件系統的樹狀的命令空間。唯一不同是每個節點和他們的子節點可以擁有關聯數據。類比到文件系統,就好像允許一個文件同時也是路徑。Zookeeper的
路徑是約定 絕對的 / 分隔的路徑,這裏沒有相對引用。任何unicode編碼的字符可以被用在path中,除了一些約束。

  • ZNodes

Zookeeper 樹的每一個節點被當作一個znode.Znodes 很多狀態結構,包括 記錄數據變化的版本號,ACL(Access Control List) 變化和時間戳。版本號和時間戳允許Zookeeper 驗證緩存和協調更新。
每次znode數據變化,版本號都會自增1.例如,當一個客戶端遍歷數據是,他同事會遍歷數據的版本號。同時當客戶端更新或者刪除數據時,它必須提供它改變目標的znode 數據的版本號。如果提供的
版本號和數據的真是的版本號不匹配,那個更新將會失敗。

Watches – 客戶端可以在Znode上設置監視器(Watchers)。改變那個znode將會觸發watch,然後清除watch.當一個watch被觸發,Zookeeper將會給客戶端發送一個通知。

Data Access – 在命令空間上每個znode存儲的數據可以被自動讀寫。讀 得到這個znode所有的字節數據,寫 替換所有的數據。沒有znode都會有一個ACL(訪問控制列表)來顯示誰可以做什麼。
Zookeeper 並不是被設計用來做一個通用的數據庫或者一個大的對象存儲。Instead, it manages coordination data(反而,它管理協調數據)。
This data can come in the form of configuration, status information, rendezvous, etc.
多種形式的協調數據的一個共同也正是他們相對而言都比較小,以KB計算。zookeeper的客戶端和服務端實現有一個明智的檢查來確保每一個節點的數據小於1M,但是數據的平均大小要少的多。
在一個相對較大的數據上操作將會導致一些操作會話費比較多的時間,同時因爲需要在網絡和存儲媒體上傳播移動帶來的額外時間可能會帶來延遲。如果一個大的數據存儲是必須的,那麼通常情況處理這些數據
的方式是存儲他們在bulk storage system,例如 NFS 或者 HDFS ,然後把指向存儲位置的指針放到zookeeper中。

Ephemeral Nodes – 臨時結點 Zookeeper還有一個臨時節點的概念。這些節點在創建這些節點的session的活動週期中存貨。當session結束,這些節點也被刪除了。因此。臨時節點不允許有子節點。

Sequence Nodes – Unique Naming 順序節點-唯一命名 當創建一個節點時,你也可以請求Zookeeper給path的結尾添加一個單調遞增的計數器。這個計數器對於父節點是獨一無二的。
計數器是%010形式,10個數字,先導0填充(這樣設計是爲了方便排序,eg:0000000001)。記住,用來存儲下一個序列的節點是一個有符號的整形術,當超過 2147483647時計數器將會溢出

Container Nodes – 容器節點 zookeeper在3.6版本後加入容器系欸按的概念。容器節點是有特別目的的節點,當作爲leader 鎖是很有用。當容器的最後一個節點被刪除,這個容器編程候選刪除項,
將會在未來的某個時間點被刪除。鑑於這個屬性,當你創建子節點而不是容器節點時,你應該有所準備得到 keeperException.NoNodeException 。所以,當你創建子節點而不是容器節點時,你總是需要
先檢查一下 KeeperException.NoNodeException,當確實有異常被捕獲時間,你需要重新創建容器節點

  • Zookeeper 中的時間

Zxid – Zookeeper 事務id .Zookeeper狀態的每次變化都會收到一個zxid(Zookeeper Transaction Id)形式的標記。這表明了zookeeper 變化的總體順序。每次改變都會有以獨一無二的zxid,如果zxid1 小於 zxid2,那麼zxid1發生的早。

Version numbers – 版本號 .節點的每次變化都會導致那個節點的版本號自增1。version 表示這個節點的數據的改變的次數,cversion 表示這個節點子節點的改變的次數,aversion 代表這個節點ACL變化的次數

Ticks – 滴答時間 . 當你用多服務器Zookeeper,服務器用ticks 定義時間的時間,例如 狀態的上傳 session的超時 每個服務連接的超時時間等等。 這個tick時間是最小的session超時時間(2倍的tick time)的間接標識方式。
如果你個客戶端請求的session超時時間小於 最小的session超時時間,那麼服務器將會告訴客戶端 session超時時間事實上是最小的session超時時間

Real time – 實時時間 .Zookeeper除了znode的創建和修改時把時間戳放到znode的狀態結構中,不用實時時間或者時鐘時間

  • Zookeeper 的 狀態結構

每個Zookeeper的節點都有下面一個域組成:

czxid – znode被創建的zxid
mzxid – znode最後一次被修改的zxid
pzxid – znode的子節點最後一次被修改的zxid
ctime – znode被創建時從新時代(1970?)的毫秒數
mtime – znode最後一次被修改時從新時代(1970?)的毫秒數
version – znode數據改變的次數
cversion – znode子節點數據數據改變的次數
aversion – znode ACL 改變的次數
ephemeralOwner – 如果這個節點是臨時節點,那麼就是這個節點擁有者的session id ;否則,爲0
dataLength – znode數據的長度
numChildren – znode子節點的個數


2. Zookeeper Sessions

每一個zookeeper客戶端和zookeeper服務之間通過創建語言綁定創建一個handle來建立一個session.一旦被創建,handle 以 CONNECTING 狀態啓動, 客戶端類庫嘗試連接服務中一個服務器,
在那個節點狀態切換爲 CONNECTED 狀態。日常操作中,狀態通常是這兩者其中之一。如果一個不可恢復的錯誤發生,比如session過期 或者驗證失敗 應用程序顯示關閉handle 等等, 那時handle
的狀態就轉化爲 CLOSED 狀態了。

session

爲了創建客戶端session , 程序代碼必須提供一個逗號分隔的 host:post 形式的字符串列表,每一次對應一個zookeeper 服務(eg: “127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002”)
zookeeper客戶端將會人影挑選一個服務器,嘗試連接它。如果鏈接失敗 或者 服務器以某種理由拒絕鏈接,客戶端將會自動嘗試連接列表中的下一臺服務器,直到一個連接是可以建立的。

From 3.2 一個可選的”chroot”後綴可以被追加到連接字符串後面。類似於unixde chroot命令,當運行這個命令時,就會解釋所有的相對於這個root的路徑。
eg:”127.0.0.1:4545/app/a” root路徑被切換爲”/app/a” ,所有的路徑將會以此作爲根 。”/foo/bar” 就變成了 “/app/a/foo/bar”
這個功能在多用戶環境中將會很有用,zookeeper的每個用戶將會由不同的根路徑。這使得每個用戶的代碼重用變得很簡單,開發時是/ ,當真正部署時用 一個不同的路徑

當一個client得到一個zookeeper服務的handle,zookeeper會創建一個session,並用一個64bit的數字代表它,並將這個值複製給client。如果client連接不同的zookeeper服務,它將會把session id
作爲握手連接的一部分。作爲一種安全措施,服務器爲session id 創建一個密碼,任何zookeeper 服務器都可以驗證它。當client建立session時,密碼和session id 一起傳遞給客戶端。
當和一個新的服務器恢復session 時,客戶端傳遞密碼和session id 。

zookeeper客戶端類庫創建session的參數之一是 session的超時時間(毫秒)。客戶端發送一個請求超時,服務端返回給他這個超時。當前的實現需要這個時間最小要是2倍的tickTime(在服務端配置中),
最大是20倍的tickTime.Zookeeper 客戶端api允許協商超時。

如果一個客戶端session從zookeeper集羣變成一個分區的,它將開始搜索session創建時指定的服務器列表。最終,當客戶端和至少一個服務器的連通性被重新建立,session還是要轉化到
CONNECTED狀態(在sessionc超時時間內重新連接) 或者轉化爲 expired過期狀態(在超時時間後重新連接)。爲了斷開連接而創建一個新的連接是不明智的。zookeeper 的客戶端將會爲你重新連接。
特別的,我們試探性的用內置的客戶端烈苦處理事情,類似於”羊羣效應” 當你被通知session過期時,會被創建一個新的session

session 的過期是被zookeeper集羣所管理的,而不是zk client.當zk client 和zookeeper 集羣建立session時,它提供了一個 “timeout”的值在最上面。這個值被集羣用來決定客戶端session什麼時間超時。
集羣發生在集羣不再特定的session超時週期中受到客戶端的信息(no heartbeat).當session過期時,集羣將會刪除所有屬於這個session的臨時節點,並且立即通知所有連接(任何watch those node的)客戶端這個變化。
在這個節點過期session的客戶端依然是斷開連接的,所以知道下次重新和集羣建立連接纔會被通知到。這個客戶端依然保持斷開連接的狀態,直到TCP重新建立,在那個節點 過期session的監視器將會收到”session expired”的通知

過期session 監視器眼中的 過期session的狀態轉變
1. ‘connected’:session被建立 並且 客戶端和集羣處於連接中(client/server通信正常運行)
2. client 被集羣分區
3. ‘disconnected’:客戶端和服務端失去連通性
4. 時間飛逝,’timeout’之後集羣將session置爲失效,因爲client已經失去連接,所有它什麼都看不到
5. 時間飛逝,客戶端重新獲得和集羣的網絡連接
6. ‘expired’:最終客戶端重新連接到集羣,它被通知爲過期了

另一個zookeeper session建立調用的另一個參數是默認watcher .客戶端任何的狀態改變,watcher 都會通知。例如,如果 client斷開連接,或者客戶端session超時 客戶端應該考慮初始狀態爲 disconnected(在
任何狀態改變時間被髮送到watcher之前)。在這個新的連接用例中,發送給watcher的第一個事件應該是 連接事件。

客戶端持續發送的請求是session存活的必要條件。如果一個session在一個週期內是閒置的,這將會導致session超時,所以client將會發送一個PING連接來保證session是存活的。PING請求不僅允許zookeeper服務器
知道客戶端依然存活,同時也會客戶端驗證是否zookeeper服務依然活躍。PING連接的頻率足夠保守,可以確保這是一個 察覺死連接和重新連接到一個新的server 的 合適時間。

一旦一個服務器連接被成功建立,無論是同步操作 還是異步操作 下面的兩種情況都會導致 異常 (in java):
1. 應用程序在一個 不再存活/有效 的session 調用操作
2. 當有一個延遲(pending)操作 zookeeper 客戶端和服務器斷開連接

from 3.2 SessionMovedException 19.22.0

服務器列表的更新 我們允許客戶端提供一個新的 逗號分隔的host:post 連接字符串來更新連接。例如 如果原來有5個host,現在移掉2個,原來連接到3的連接不變;連接到另外兩個host的連接將會隨機連接到剩下
的3個host.如果連接被關掉,客戶端將會用概率算法來選擇一個新的server連接。


3. Zookeeper Watcher

在zookeeper中,所有的讀操作是有三種 getData() getChildren() 和 exists().wacth在zookeeper中的定義,一個watch時間是一次觸發的,當watch的數據被改變時 傳遞給設置watch的客戶端。
watch定義中的三個關鍵點:

one-time trigger 一次觸發器
當數據改變時,一個wathch事件可以被傳遞給客戶端。例如,如果一個客戶端調用了 getData(‘/znode1’,’true’) ,然後如果/znode1的數據被改變或者刪除,客戶端將會收到一個/znode1的時間。如果
/znode1再次改變,將沒有watch時間被傳遞。除非客戶端再進行一個讀操作,這會隱示的設置一個新的watch

send to the client 發給客戶端
一個事件的暗示是給客戶端的。watche 是被異步傳遞的.zookeeper 會保證順序。 網絡延遲或者其他的影響因素將會導致不同的客戶端在不同的時間看到watch並返回狀態碼。關鍵點是被不同的客戶端看到
一切都有一個一致性順序。

The Data from which the watch was set 被觀察的數據
node的改變有兩種不同的watch ,一種是data watches ,一種是chrild watches. getData() 和 exists() 設置 dara watches;getChildren() 設置 child Watchers.
通過數據的返回類型也能更好的額理解,getDat() 和 exists() 放回節點data的信息 ,然而 getChildren 返回子節點的列表。所以setData()將會觸發data watches 。
create()將會觸發當前節點的data watch 和父節點的child watches。delete() 也會觸發 data watcher 和 child watch。

watches的元語
Created event : 可以被 exists 觸發
Deleted event : 可以被 exists getData getChildren 觸發
Changed event : 可以被 exists getData 觸發
Child event : 可以被 getChildren 觸發

移除watches
我們可以通過removeWatches 來移除註冊在節點上的watches.
Child Remove event : 當node被設置getChildren
Data Remove event : 當node被設置exists 或者 getData

zookeeper對於watches的保證


4. zookeeper用ACL實現權限控制

zookeeper 通過ACLs lai kongzhi znode的權限。ACL的實現有點類似於UNIX文件的權限控制,他用允許/不允許多種操哦做來限定node的訪問方位。不想標準的UNIXq權限,一個zookeeper節點
沒有被區分爲三種不同的用戶標準組(user group other).zookeeper 沒有節點擁有者這個概念,一個ACL指定了id和權限組成的列表集合、

ACL 只對一個節點有效,它不會應用到子節點。ACL不會遞歸傳遞的。

zookeeper 支持可插拔式的權限驗證模式。Ids的形式通常是scheme:id,

ACL 有 (scheme:expression,perms) 這樣鍵值對組成。eg: (ip:19.22.0.0/16,READ) 授予ip地址以19.22開頭的客戶端 READ權限。

ACL的權限
CREATE : 你可以創建一個子節點
READ : 你可以得到節點的數據和子節點列表
WRITE : 你可以爲節點設置數據
DELETE : 你可以刪除子節點
ADMIN : 你可以設置權限

CREATE 和 DELETE 提供了比 WRITE 更爲細粒度的權限控制。

ACL 內建的一些元語
world - 代表 任何人
auth - 代表 任何驗證通過的用戶
digest - 用 usernam額:password 字符串生成MD5 hash 值,那將會用來作爲ACL ID 。
ip - 用客戶端IP作爲 ACL ID
x509 -

可插拔的zookeeper權限驗證


5. 一致性保證 Consistency Guarntees

zookeeper 是一個高性能的可擴展的服務。讀寫操作被設計都很快,儘管讀比寫快一些。其中的原因是 當在讀的時候,zookeeper 可以使用舊數據。zookeeper一致性保證的原因:

Sequential Consistency : 順序保證。從客戶端的更新將會以它們發送的順序來應用
Atomicity : 原子性 更新要麼成功要麼失敗,沒有其他結果
Single System Image : 無論客戶端連接到那個服務器,他看到的將是一樣的數據
Reliability : 可靠型。一旦一個更新被應用。 兩個推論 …
Timeliness :

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章