[轉]Zookeeper系列(一)

1、ZooKeeper的背景java

1.1 認識ZooKeepernode

ZooKeeper---譯名爲「動物園管理員」。動物園裏固然有好多的動物,遊客能夠根據動物園提供的嚮導圖到不一樣的場館觀賞各類類型的動物,而不是像走在原始叢林裏,心驚膽顫的被動 物所觀賞。爲了讓各類不一樣的動物呆在它們應該呆的地方,而不是相互串門,或是相互廝殺,就須要動物園管理員按照動物的各類習性加以分類和管理,這樣咱們才能更加放心安全的觀賞動物。mysql

回到企業級應用系統中,隨着信息化水平的不斷提升,企業級系統變得愈來愈龐大臃腫,性能急劇降低,客戶抱怨頻頻。拆分系統是目前咱們可選擇的解決系統可伸縮性和性能問題的惟一行之有效的方法。可是拆分系統同時也帶來了系統的複雜性——各子系統不是孤立存在的,它們彼此之間須要協做和交互,這就是咱們常說的分佈式系統0。各個子系統就比如動物園裏的動物,爲了使各個子系統能正常爲用戶提供統一的服務,必須須要一種機制來進行協調——這就是ZooKeeper(動物園管理員)。算法

1.2 爲何使用ZooKeepersql

咱們知道要寫一個分佈式應用是很是困難的,主要緣由就是局部故障。一個消息經過網絡在兩個節點之間傳遞時,網絡若是發生故障,發送方並不知道接收方是否接收到了這個消息。他可能在網絡故障遷就收到了此消息,也坑沒有收到,又或者可能接收方的進程死了。發送方瞭解狀況的惟一方法就是再次鏈接發送方,並向他進行詢問。這就是局部故障:根本不知道操做是否失敗。所以,大部分分佈式應用須要一個主控、協調控制器來管理物理分佈的子進程。目前,大部分應用須要開發私有的協調程序,缺少一個通用的機制。協調程序的反覆編寫浪費,且難以造成通用、伸縮性好的協調器。協調服務很是容易出錯,並很難從故障中恢復。例如:協調服務很容易處於競態1甚至死鎖2。Zookeeper的設計目的,是爲了減輕分佈式應用程序所承擔的協調任務。數據庫

Zookeeper並不能阻止局部故障的發生,由於它們的本質是分佈式系統。他固然也不會隱藏局部故障。ZooKeeper的目的就是提供一些工具集,用來創建安全處理局部故障的分佈式應用。express

ZooKeeper是一個分佈式小文件系統,而且被設計爲高可用性。經過選舉算法和集羣複製能夠避免單點故障3,因爲是文件系統,因此即便全部的ZooKeeper節點所有掛掉,數據也不會丟失,重啓服務器以後,數據便可恢復。另外ZooKeeper的節點更新是原子的,也就是說更新不是成功就是失敗。經過版本號,ZooKeeper實現了更新的樂觀鎖4,當版本號不相符時,則表示待更新的節點已經被其餘客戶端提早更新了,而當前的整個更新操做將所有失敗。固然全部的一切ZooKeeper已經爲開發者提供了保障,咱們須要作的只是調用API。與此同時,隨着分佈式應用的的不斷深刻,須要對集羣管理逐步透明化監控集羣和做業狀態,能夠充分利ZK的獨有特性。apache

1.3 ZooKeeper的應用 安全

ZooKeeper本質上是一個分佈式的小文件存儲系統。本來是Apache Hadoop的一個組件,如今被拆分爲一個Hadoop的獨立子項目,在Hbase(Hadoop的另一個被拆分出來的子項目,用於分佈式環境下的超大數據量的DBMS)中也用到了ZooKeeper集羣。 服務器

Hadoop,使用Zookeeper的事件處理確保整個集羣只有一個NameNode,存儲配置信息等.
  HBase,使用Zookeeper的事件處理確保整個集羣只有一個HMaster,察覺HRegionServer聯機和宕(dàng)機,存儲訪問控制列表等。

有人會懷疑ZooKeeper的執行能力,在ZooKeeper誕生的地方——Yahoo!他被用做雅虎消息代理的協調和故障恢復服務。雅虎消息代理是一個高度可擴展的發佈-訂閱系統,他管理着成千上萬臺聯及程序和信息控制系統。它的吞吐量標準已經達到大約每秒10000基於寫操做的工做量。對於讀操做的工做量來講,它的吞吐量標準還要高几倍。

2、ZooKeeper的介紹

2.1 ZooKeeper的概述

Zookeeper 是爲分佈式應用程序提供高性能協調服務的工具集合,也是Google的Chubby一個開源的實現,是Hadoop 的分佈式協調服務。它包含一個簡單的原語集5,分佈式應用程序能夠基於它實現配置維護、命名服務、分佈式同步、組服務等。Zookeeper能夠用來保證數據在ZK集羣之間的數據的事務性一致6。其中ZooKeeper提供通用的分佈式鎖服務7,用以協調分佈式應用。

Zookeeper做爲Hadoop項目中的一個子項目,是 Hadoop集羣管理的一個必不可少的模塊,它主要用來解決分佈式應用中常常遇到的數據管理問題,如集羣管理、統一命名服務、分佈式配置管理、分佈式消息隊列、分佈式鎖、分佈式協調等。在Hadoop中,它管理Hadoop集羣中的NameNode,還有在Hbase中Master Election、Server 之間狀態同狀步等。
  Zoopkeeper 提供了一套很好的分佈式集羣管理的機制,就是它這種基於層次型的目錄樹的數據結構,並對樹中的節點進行有效管理,從而能夠設計出多種多樣的分佈式的數據管理模型。

2.2 ZooKeeper的設計目標

衆所周知,分佈式環境下的程序和活動爲了達到協調一致目的,一般具備某些共同的特色,例如,簡單性、有序性等。ZooKeeper不但在這些目標的實現上有自身特色,而且具備獨特優點。下面咱們將簡述ZooKeeper的設計目標。

(1)簡單化

ZooKeeper容許各分佈式進程經過一個共享的命名空間相互聯繫,該命名空間相似於一個標準的層次型的文件系統:由若干註冊了的數據節點構成(用Zookeeper的術語叫znode),這些節點相似於文件和目錄。典型的文件系統是基於存儲設備的,文傳統的文件系統主要用於存儲功能,然而ZooKepper的數據是保存在內存中的。也就是說,能夠得到高吞吐和低延遲。ZooKeeper的實現很是重視高性能、高可靠,以及嚴格的有序訪問。

高性能保證了ZooKeeper能夠用於大型的分佈式系統,高可靠保證了ZooKeeper不會發生單點故障,嚴格的順序訪問保證了客戶端能夠得到複雜的同步操做原語。

(2)健壯性

就像ZooKeeper須要協調的分佈式系統同樣,它自己就是具備冗餘結構,它構建在一系列主機之上,叫作一個」ensemble」。
  構成ZooKeeper服務的各服務器之間必須相互知道,它們維護着一個狀態信息的內存映像8,以及在持久化存儲中維護着事務日誌和快照9。只要大部分服務器正常工做,ZooKeeper服務就能正常工做。
  客戶端鏈接到一臺ZooKeeper服務器。客戶端維護這個TCP鏈接,經過這個鏈接,客戶端能夠發送請求、獲得應答,獲得監視事件以及發送心跳。若是這個鏈接斷了,客戶端能夠鏈接到另外一個ZooKeeper服務器。

(3)有序性

ZooKeeper給每次更新附加一個數字標籤,代表ZooKeeper中的事務順序,後續操做能夠利用這個順序來完成更高層次的抽象功能,例如同步原語7。

(4)速度優點

ZooKeeper特別適合於以讀爲主要負荷的場合。ZooKeeper能夠運行在數千臺機器上,若是大部分操做爲讀,例如讀寫比例爲10:1,ZooKeeper的效率會很高。

2.3 ZooKeeper的集羣

ZK集羣以下圖2.1所示。這是實際應用的一個場景,該ZooKeeper集羣當中一共有5臺服務器,有兩種角色Leader和Follwer,5臺服務器連通在一塊兒,客戶端有分別連在不一樣的ZK服務器上。若是當數據經過客戶端1,在左邊第一臺Follower服務器上作了一次數據變動,他會把這個數據的變化同步到其餘全部的服務器,同步結束以後,那麼其餘的客戶端都會得到這個數據的變化。

圖 2.1

注意:

一般Zookeeper由2n+1臺servers組成,每一個server都知道彼此的存在。每一個server都維護的內存狀態鏡像以及持久化存儲的事務日誌和快照。爲了保證Leader選舉能過獲得多數的支持,因此ZooKeeper集羣的數量通常爲奇數。對於2n+1臺server,只要有n+1臺(大多數)server可用,整個系統保持可用。

2.3.1 集羣中的角色

在ZooKeeper集羣當中,集羣中的服務器角色有兩種Leader和Learner,Learner角色又分爲Observer和Follower,具體功能以下:

1.領導者(leader),負責進行投票的發起和決議,更新系統狀態

2.學習者(learner),包括跟隨者(follower)和觀察者(observer),

3.follower用於接受客戶端請求並向客戶端返回結果,在選主過程當中參與投票

4.Observer能夠接受客戶端請求,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態,observer的目的是爲了擴展系統,提升讀取速度。

5. 客戶端(client),請求發起方

ZooKeeper的組件圖中給出了ZooKeeper服務的高層次的組件。除了請求處理器(requestprocessor)外,構成ZooKeeper服務的每一個服務器都有一個備份。複製的數據庫(replicateddatabase)是一個內存數據庫,包含整個數據樹。爲了可恢復,更新會被log到磁盤,而且在更新這個內存數據庫以前,先序列化到磁盤。

每一個ZooKeeper都爲客戶端提供服務。客戶端只鏈接到一個服務器,並提交請求。讀請求直接由本地的複製數據庫提供數據。對服務狀態進行修改的請求、寫請求經過一個約定的協議進行通信。

做爲這個協議的一部分,全部的寫請求都被傳送到一個叫「首領(leader)」的服務器,而其餘的服務器,叫作「(隨從)followers」,follower從leader接收信息修改的提議,並贊成進行。當leader發生故障時,協議的信息層(messaginglayer)關注leader的替換,並同步到全部的follower。

ZooKeeper採用一個自定義的信息原子操做協議,因爲信息層的操做是原子性的,ZooKeeper能保證本地的複製數據庫不會產生不一致。當leader接收到一個寫請求,它計算出寫以後系統的狀態,把它變成一個事務。

2.3.2 Zookeeper的讀寫機制和保證及特色

(1)ZooKeeper的讀寫機制

Zookeeper是一個由多個server組成的集羣

一個leader,多個follower

每一個server保存一份數據副本

全局數據一致

分佈式讀寫

更新請求轉發,由leader實施

(2)ZooKeeper的保證

ZooKeeper運行很是快並且簡單。雖然它的目標是構建更加複雜服務(例如同步)的基礎,但它提供了一些保證,以下:

1.順序一致性:來自於客戶端的更新,根據發送的前後被順序實施。

2.惟一的系統映像:儘管客戶端鏈接到不一樣的服務器,但它們看到的一個惟一(一致性)的系統服務,client不管鏈接到哪一個server,數據視圖都是一致的。

3.可靠性:一旦實施了一個更新,就會一直保持那種狀態,直到客戶端再次更新它,同時數據更新原子性,一次數據更新要麼成功,要麼失敗。

4.及時性:在一個肯定的時間內,客戶端看到的系統狀態是最新的。

(3)ZooKeeper特色

最終一致性:client不論鏈接到哪一個Server,展現給它都是同一個視圖,這是zookeeper最重要的性能。

可靠性:具備簡單、健壯、良好的性能,若是消息m被一臺服務器接受,那麼它將被全部的服務器接受。

實時性:Zookeeper保證客戶端將在一個時間間隔範圍內得到服務器的更新信息,或者服務器失效的信息。 但因爲網絡延時等緣由,Zookeeper不能保證兩個客戶端能同時獲得剛更新的數據,若是須要最新數據,應該在讀數據以前調用sync()接口。

等待無關(wait-free):慢的或者失效的client,不得干預快速的client的請求,使得每一個client都能有效的等待。

原子性:更新只能成功或者失敗,沒有中間狀態。

順序性:包括全局有序和偏序兩種:

全局有序:是指若是在一臺服務器上消息a在消息b前發佈,則在全部Server上消息a都將在消息b前被髮布;

偏序:是指若是一個消息b在消息a後被同一個發送者發佈,a必將排在b前面

3、ZooKeeper服務

3.1 ZooKeeper數據模型

ZooKeeper擁有一個層次的命名空間,這個和分佈式的文件系統很是類似。不一樣的是ZooKeeper命名空間中的Znode,兼具文件和目錄兩種特色。既像文件同樣維護着數據、元信息、ACL、時間戳等數據結構,又像目錄同樣能夠做爲路徑標識的一部分,並能夠具備子znode。用戶對znode具備增、刪、改、查等操做(權限容許的狀況下)。

znode具備原子性操做,每一個znode的數據將被原子性地讀寫,讀操做會讀取與znode相關的全部數據,寫操做會一次性替換全部數據。zookeeper並無被設計爲常規的數據庫或者大數據存儲,相反的是,它用來管理調度數據,好比分佈式應用中的配置文件信息、狀態信息、聚集位置等等。這些數據的共同特性就是它們都是很小的數據,一般以KB爲大小單位。zooKeeper的服務器和客戶端都被設計爲嚴格檢查並限制每一個znode的數據大小至多1M,當時常規使用中應該遠小於此值。

Zonde由路徑標註,ZooKeeper中被表示成有反斜槓分割的Unicode字符串,如同Unix中的文件路徑。路徑必須是絕對的,所以他們必須由反斜槓來字符開頭。除此之外,他們必須是惟一的,也就是說每個路徑只有一個表示,所以這些路徑不能改變。ZooKeeper的數據結構, 與普通的文件系統極爲相似. 見下圖:

圖中的每一個節點稱爲一個znode. 每一個znode由3部分組成:

1.stat:此爲狀態信息, 描述該znode的版本, 權限等信息.

2.data:與該znode關聯的數據.

3.children:該znode下的子節點.

3.1.1 ZooKeeper節點Znode

ZooKeeper目錄樹中每個節點對應一個Znode。每一個Znode維護着一個屬性結構,它包含着版本號(dataVersion),時間戳(ctime,mtime)等狀態信息。ZooKeeper正是使用節點的這些特性來實現它的某些特定功能。每當Znode的數據改變時,他相應的版本號將會增長。每當客戶端檢索數據時,它將同時檢索數據的版本號。而且若是一個客戶端執行了某個節點的更新或刪除操做,他也必須提供要被操做的數據版本號。若是所提供的數據版本號與實際不匹配,那麼這個操做將會失敗。

Znode是客戶端訪問ZooKeeper的主要實體,它包含如下幾個特徵:

(1)Watches

客戶端能夠在節點上設置watch(咱們稱之爲監視器)。當節點狀態發生改變時(數據的增、刪、改)將會觸發watch所對應的操做。當watch被觸發時,ZooKeeper將會向客戶端發送且僅發送一條通知,由於watch只能被觸發一次。

(2)數據訪問

ZooKeeper中的每一個節點存儲的數據要被原子性的操做。也就是說讀操做將獲取與節點相關的全部數據,寫操做也將替換掉節點的全部數據。另外,每個節點都擁有本身的ACL(訪問控制列表),這個列表規定了用戶的權限,即限定了特定用戶對目標節點能夠執行的操做。

(3)節點類型

ZooKeeper中的節點有兩種,分別爲臨時節點和永久節點。節點的類型在建立時即被肯定,而且不能改變。
  ZooKeeper的臨時節點:該節點的生命週期依賴於建立它們的會話。一旦會話結束,臨時節點將被自動刪除,固然能夠也能夠手動刪除。另外,須要注意是,ZooKeeper的臨時節點不容許擁有子節點。
  ZooKeeper的永久節點:該節點的生命週期不依賴於會話,而且只有在客戶端顯示執行刪除操做的時候,他們才能被刪除。

(4)順序節點(惟一性的保證)

當建立Znode的時候,用戶能夠請求在ZooKeeper的路徑結尾添加一個遞增的計數。這個計數對於此節點的父節點來講是惟一的,它的格式爲「%10d」(10位數字,沒有數值的數位用0補充,例如「0000000001」)。當計數值大於232-1時,計數器將溢出。

org.apache.zookeeper.CreateMode中定義了四種節點類型,分別對應:

PERSISTENT:永久節點

EPHEMERAL:臨時節點

PERSISTENT_SEQUENTIAL:永久節點、序列化

EPHEMERAL_SEQUENTIAL:臨時節點、序列化

3.1.2 ZooKeeper中的時間

ZooKeeper有多種記錄時間的形式,其中包含如下幾個主要屬性:

(1)Zxid

導致ZooKeeper節點狀態改變的每個操做都將使節點接收到一個zxid格式的時間戳,而且這個時間戳全局有序。也就是說,也就是說,每一個對節點的改變都將產生一個惟一的zxid。若是zxid1的值小於zxid2的值,那麼zxid1所對應的事件發生在zxid2所對應的事件以前。實際上,ZooKeeper的每一個節點維護者三個zxid值,爲別爲:cZxid、mZxid、pZxid。

cZxid: 是節點的建立時間所對應的Zxid格式時間戳。

mZxid:是節點的修改時間所對應的Zxid格式時間戳。

實現中zxid是一個64爲的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個 新的epoch。低32位是個遞增計數。

(2)版本號

對節點的每個操做都將導致這個節點的版本號增長。每一個節點維護着三個版本號,他們分別爲:

version 節點數據版本號

cversion 子節點版本號

aversion 節點所擁有的ACL版本號

3.1.3 節點的屬性結構

經過前面的介紹,咱們能夠了解到,一個節點自身擁有表示其狀態的許多重要屬性,以下圖所示。

3.1.4 Zonde總結

(1)znode中的數據能夠有多個版本,在查詢該znode數據時就須要帶上版本信息。如:set path version / delete path version

(2)znode能夠是臨時znode,由create -e 生成的節點,一旦建立這個znode的client與server斷開鏈接,該znode將被自動刪除。

client和server之間經過heartbeat來確認鏈接正常,這種狀態稱之爲session,斷開鏈接後session失效。

(3)臨時znode不能有子znode。

(4)znode能夠自動編號,由create -s 生成的節點,例如在 create -s /app/node 已存在時,將會生成 /app/node00***001節點。

(5)znode能夠被監控,該目錄下某些信息的修改,例如節點數據、子節點變化等,能夠主動通知監控註冊的client。事實上,經過這個特性,能夠完成許多重要應用,例如配置管理、信息同步、分佈式鎖等等。

3.2 ZooKeeper服務中的操做

在ZooKeeper中有9個基本操做,以下圖所示:

更新ZooKeeper操做是有限制的。delete或setData必須明確要更新的Znode的版本號,咱們能夠調用exists找到。若是版本號不匹配,更新將會失敗。

更新ZooKeeper操做是非阻塞式的。所以客戶端若是失去了一個更新(因爲另外一個進程在同時更新這個Znode),他能夠在不阻塞其餘進程執行的狀況下,選擇從新嘗試或進行其餘操做。

儘管ZooKeeper能夠被看作是一個文件系統,可是處於便利,摒棄了一些文件系統地操做原語。由於文件很是的小而且使總體讀寫的,因此不須要打開、關閉或是尋地的操做。

3.2.1 watch觸發器

讀操做exists、getChildren和getData都被設置了watch,而且這些watch都由寫操做來觸發:create、delete和setData。ACL操做並不參與到watch中。當watch被觸發時,watch事件被生成,他的類型由watch和觸發他的操做共同決定。ZooKeeper所管理的watch能夠分爲兩類:

1.數據watch(data watches):getData和exists負責設置數據watch;

2.孩子watch(child watches):getChildren負責設置孩子watch;

咱們能夠經過操做返回的數據來設置不一樣的watch:

1.getData和exists:返回關於節點的數據信息

2.getChildren:返回孩子列表

所以,一個成功的setData操做將觸發Znode的數據watch。

一個成功的create操做將觸發Znode的數據watch以及孩子watch。

一個成功的delete操做將觸發Znode的數據watch以及孩子watch。

watch由客戶端所鏈接的ZooKeeper服務器在本地維護,所以watch能夠很是容易地設置、管理和分派。當客戶端鏈接到一個新的服務器上時,任何的會話事件都將可能觸發watch。另外,當從服務器斷開鏈接的時候,watch將不會被接收。可是,當一個客戶端從新創建鏈接的時候,任何先前註冊過的watch都會被從新註冊。

exists操做上的watch,在被監視的Znode建立、刪除或數據更新時被觸發。

getData操做上的watch,在被監視的Znode刪除或數據更新時被觸發。在被建立時不能被觸發,由於只有Znode必定存在,getData操做纔會成功。

getChildren操做上的watch,在被監視的Znode的子節點建立或刪除,或是這個Znode自身被刪除時被觸發。能夠經過查看watch事件類型來區分是Znode仍是他的子節點被刪除:NodeDelete表示Znode被刪除,NodeDeletedChanged表示子節點被刪除。

watch設置操做及相應的觸發器如圖下圖所示:

watch事件包括了事件所涉及的Znode的路徑,所以對於NodeCreated和NodeDeleted事件來講,根據路徑就能夠簡單區分出是哪一個Znode被建立或是被刪除了。爲了查詢在NodeChildrenChanged事件後哪一個子節點被改變了,須要再次調用getChildren來得到新的children列表。一樣的,爲了查詢NodeDeletedChanged事件後產生的新數據,須要調用getData。在兩種狀況下,Znode可能在獲取watch事件或執行讀操做這兩種狀態下切換,在寫應用程序時,必須記住這一點。

(1)Zookeeper的watch實際上要處理兩類事件:

1. 鏈接狀態事件(type=None, path=null)

這類事件不須要註冊,也不須要咱們連續觸發,咱們只要處理就好了。

2. 節點事件

節點的創建,刪除,數據的修改。它是one time trigger,咱們須要不停的註冊觸發,還可能發生事件丟失的狀況。

上面2類事件都在Watch中處理,也就是重載的process(Event event)

(2)節點事件的觸發,經過函數exists,getData或getChildren來處理

這類函數,有雙重做用:

1. 註冊觸發事件

2. 函數自己的功能

函數的自己的功能又能夠用異步的回調函數來實現,重載processResult()過程當中處理函數自己的的功能。

函數還能夠指定本身的watch,因此每一個函數都有4個版本。根據本身的須要來選擇不一樣的函數,不一樣的版本。

3.3 ZooKeeper訪問控制列表ACL

ZooKeeper使用ACL來對Znode進行訪問控制。ACL的實現和Unix文件訪問許可很是類似:它使用許可位來對一個節點的不一樣操做進行容許或禁止的權限控制。可是,和標準的Unix許可不一樣的是,Zookeeper對於用戶類別的區分,不止侷限於全部者(owner)、組 (group)、全部人(world)三個級別。Zookeeper中,數據節點沒有「全部者」的概念。訪問者利用id標識本身的身份,並得到與之相應的 不一樣的訪問權限。

注意:

傳統的文件系統中,ACL分爲兩個維度,一個是屬組,一個是權限,子目錄/文件默認繼承父目錄的ACL。而在Zookeeper中一個ACL和一個ZooKeeper節點相對應。而且,父節點的ACL與子節點的ACL是相互獨立的。也就是說,ACL不能被子節點所繼承,父節點所擁有的權限與子節點所用的權限都沒有任何關係。

Zookeeper支持可配置的認證機制。它利用一個三元組來定義客戶端的訪問權限:(scheme:expression, perms) 。其中:

1.scheme:定義了expression的含義。

如:(host:host1.corp.com,READ),標識了一個名爲host1.corp.com的主機,有該數據節點的讀權限。

2.Perms:標識了操做權限。

如:(ip:19.22.0.0/16, READ),表示IP地址以19.22開頭的主機,有該數據節點的讀權限。

Zookeeper的ACL也能夠從三個維度來理解:一是,scheme; 二是,user; 三是,permission,一般表示爲scheme:id:permissions,以下圖所示。

1.world : id格式:anyone。

如:world:anyone表明任何人,zookeeper中對全部人有權限的結點就是屬於world:anyone的。

2.auth : 它不須要id。

注:只要是經過authentication的user都有權限,zookeeper支持經過kerberos來進行認證, 也支持username/password形式的認證。

3.digest: id格式:username:BASE64(SHA1(password))。

它須要先經過username:password形式的authentication。

4.ip: id格式:客戶機的IP地址。

設置的時候能夠設置一個ip段。如:ip:192.168.1.0/16, 表示匹配前16個bit的IP段

5.super: 超級用戶模式。

在這種scheme狀況下,對應的id擁有超級權限,能夠作任何事情

ZooKeeper權限定義以下圖所示:

ZooKeeper內置的ACL模式以下圖所示:

當會話創建的時候,客戶端將會進行自我驗證。另外,ZooKeeper Java API支持三種標準的用戶權限,它們分別爲:

1.ZOO_PEN_ACL_UNSAFE:對於全部的ACL來講都是徹底開放的,任何應用程序能夠在節點上執行任何操做,好比建立、列出並刪除子節點。

2.ZOO_READ_ACL_UNSAFE:對於任意的應用程序來講,僅僅具備讀權限。

3.ZOO_CREATOR_ALL_ACL:授予節點建立者全部權限。須要注意的是,設置此權限以前,建立者必須已經通了服務器的認證。

下面演示一個經過digest(用戶名密碼的方式)爲建立的節點設置ACL的例子,代碼以下:

import org.apache.zookeeper.*;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
import org.apache.zookeeper.data.*;
import java.util.*;

public class NewDigest {

    public static void main(String[] args) throws Exception {//new一個acl
        List acls = new ArrayList();   

     //添加第一個id,採用用戶名密碼形式
        Id id1 = new Id("digest",DigestAuthenticationProvider.generateDigest("admin:admin"));
        ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);
        acls.add(acl1);
        
     //添加第二個id,全部用戶可讀權限
        Id id2 = new Id("world", "anyone");
        ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);
        acls.add(acl2);

        // zk用admin認證,建立/test ZNode。
     ZooKeeper zk = new ZooKeeper("host1:2181,host2:2181,host3:2181",2000, null);
     zk.addAuthInfo("digest", "admin:admin".getBytes());
     zk.create("/test", "data".getBytes(), acls, CreateMode.PERSISTENT);
   }
}

3.4 ZooKeeper的執行

ZooKeeper服務能夠以兩種模式運行。在單機模式下,只有一個ZooKeeper服務器,便於用來測試。可是他沒有高可用性和恢復性的保障。在工業界,ZooKeeper以複合模式10運行在一組叫ensemble的集羣上。ZooKeeper經過複製來得到高可用性,同時,只要ensemble中大部分機器運做,就能夠提供服務。在2n+1個節點的ensemble中,能夠承受n臺機器故障。

ZooKeeper的思想很是簡單:他所須要作的就是保證對Znode樹的每一次修改都複製到ensemble中的大部分機器上去。若是機器中的小部分出故障了,那麼至少有一臺機器將會恢復到最新狀態,其餘的則保存這副本,直到最終達到最新狀態。Zookeeper採用Zab協議,它分爲兩個階段,而且可能被無限的重複。

(1)階段1:領導者選舉

在ensemble中的機器要參與一個選擇特殊成員的進程,這個成員叫領導者,其餘機器腳跟隨者。在大部分的跟隨者與他們的領導者同步了狀態之後,這個階段纔算完成。

(2)階段2:原子廣播

全部的寫操做請求被傳送給領導者,並經過廣播將更新信息告訴跟隨者。當大部分跟隨者執行了修改以後,領導者就提交更新操做,客戶端將獲得更新成功的迴應。未得到一致性的協議被設計爲原子的,所以不管修改失敗與否,他都分兩階段提交。

若是領導者出故障了,城下的機器將會再次進行領導者選舉,並在新領導被選出前繼續執行任務。若是在不久後老的領導者恢復了,那麼它將以跟隨者的身份繼續運行。領導者選舉很是快,由發佈的結果所知,大約是200毫秒,所以在選舉是性能不會明顯減慢。
全部在ensemble中的機器在更新它們內存中的Znode樹以前會先將更新信息寫入磁盤。讀操做請求可由任何機器服務,同時,因爲他們只涉及內存查找,所以很是快。

3.5 ZooKeeper一致性

在ensemble中的領導者和跟隨着很是靈活,跟隨者經過更新號來滯後領導者11,結果致使了只要大部分而不是全部的ensemble中的元素確認更新,就能被提交了。對於ZooKeeper來講,一個較好的智能模式是將客戶端鏈接到跟着領導者的ZooKeeper服務器上。客戶端可能被鏈接到領導者上,但他不能控制它,並且在以下狀況時,甚至可能不知道。參見下圖:

每個Znode樹的更新都會給定一個惟一的全局標識,叫zxid(表示ZooKeeper事務「ID」)。更新是被排序的,所以若是zxid的z1<z2,那麼z1就比z2先執行。對於ZooKeeper來講,這是分佈式系統中排序的惟一標準。

ZooKeeper是一種高性能、可擴展的服務。ZooKeeper的讀寫速度很是快,而且讀的速度要比寫快。另外,在進行讀操做的時候,ZooKeeper依然可以爲舊的數據提供服務。這些都是由ZooKeeper所提供的一致性保證的,它具備以下特色:

(1)順序一致性

任何一個客戶端的更新都按他們發送的順序排序,也就意味着若是一個客戶端將Znode z的值更新爲值a,那麼在以後的操做中,他會將z更新爲b,在客戶端發現z帶有值b以後,就不會再看見帶有值a的z。

(2)原子性

更新不成功就失敗,這意味着若是更新失敗了,沒有客戶端會知道。☆☆

(3)單系統映像☆

不管客戶端鏈接的是哪臺服務器,他與系統看見的視圖同樣。這就意味着,若是一個客戶端在相同的會話時鏈接了一臺新的服務器,他將不會再看見比在以前服務器上看見的更老的系統狀態,當服務器系統出故障,同時客戶端嘗試鏈接ensemble中的其餘機器時,故障服務器的後面那臺機器將不會接受鏈接,直到它鏈接到故障服務器。

(4)容錯性☆☆☆

一旦更新成功後,那麼在客戶端再次更新他以前,他就固定了,將再也不被修改,這就會保證產生下面兩種結果:

若是客戶端成功的得到了正確的返回代碼,那麼說明更新已經成功。若是不可以得到返回代碼(因爲通訊錯誤、超時等緣由),那麼客戶端將不知道更新是否生效。

當故障恢復的時候,任何客戶端可以看到的執行成功的更新操做將不會回滾。

(5)實時性☆☆

在任何客戶端的系統視圖上的的時間間隔是有限的,所以他在超過幾十秒的時間內部會過時。這就意味着,服務器不會讓客戶端看一些過期的數據,而是關閉,強制客戶端轉到一個更新的服務器上。

解釋一下:

因爲性能緣由,讀操做由ZooKeeper服務器的內存提供,並且不參與寫操做的全局排序。這一特性可能會致使來自使用ZooKeeper外部機制交流的客戶端與ZooKeeper狀態的不一致。舉例來講,客戶端A將Znode z的值a更新爲a',A讓B來讀z,B讀到z的值是a而不是a’。這與ZooKeeper的保證機制是相容的(不容許的狀況較做「同步一致的交叉客戶端視 圖」)。爲了不這種狀況的發生,B在讀取z的值以前,應該先調用z上的sync。Sync操做強制B鏈接上的ZooKeeper服務器與leader保 持一致這樣,當B讀到z的值時,他將成爲A設置的值(或是以後的值)

容易混淆的是:

sync操做只能被異步調用12。這樣操做的緣由是你不須要等待他的返回,由於ZooKeeper保證了任何接下去的操做將會發生在sync在服務器上執行之後,即便操做是在sync完成前被調用的。

這些已執行的保證後,ZooKeeper更高級功能的設計與實現將會變得很是容易,例如:leader選舉、隊列,以及可撤銷鎖等機制的實現。

3.6 ZooKeeper會話

ZooKeeper客戶端與ensemble中的服務器列表配置一致,在啓動時,他嘗試與表中的一個服務器相鏈接。若是鏈接失敗了,他就嘗試表中的其餘服務器,以此類推,知道他最終鏈接到其中一個,或者ZooKeeper的全部服務器都沒法得到時,鏈接失敗。

一旦與ZooKeeper服務器鏈接成功,服務器會建立與客戶端的一個新的對話。每一個回話都有超時時段,這是應用程序在建立它時設定的。若是服務器沒有在超時時段內獲得請求,他可能會中斷這個會話。一旦會話被中斷了,他可能再也不被打開,並且任何與會話相鏈接的臨時節點都將丟失。

不管何時會話持續空閒長達必定時間,都會由客戶端發送ping請求保持活躍(猶如心跳)。時間段要足夠小以監測服務器故障(由讀操做超時反應),而且能再回話超市時間段內從新鏈接到另外一個服務器。

在ZooKeeper中有幾個time參數。tick time是ZooKeeper中的基本時間長度,爲ensemble裏的服務器所使用,用來定義對於交互運行的調度。其餘設置以tick time的名義定義,或者至少由它來約束。

建立更復雜的臨時性狀態的應用程序應該支持更長的會話超時,由於從新構建的代價會更昂貴。在一些狀況下,咱們可讓應用程序在必定會話時間內可以重啓,而且避免會話過時。(這可能更適合執行維護或是升級)每一個會話都由服務器給定一個惟一的身份和密碼,並且若是是在創建鏈接時被傳遞給ZooKeeper的話,只要沒有過時它可以恢復會話。

這些特性能夠視爲一種能夠避免會話過時的優化,但它並不能代替用來處理會話過時。會話過時可能出如今機器忽然故障時,或是因爲任何緣由致使的應用程序安全關閉了,但在會話中斷前沒有重啓。

3.7 ZooKeeper實例狀態

Zookeeper對象的轉變是經過其生命週期中的不一樣狀態來實現。可使用getState()方法在任什麼時候候去查詢他的狀態:

public states getState()

Zookeeper狀態事務,如圖3.5所示

圖 3.5 Zookeeper狀態事務

  getState()方法的返回類型是states,states是枚舉類型表明Zookeeper對象可能所處的不一樣狀態,一個Zookeeper實例可能一次只處於一個狀態。一個新建的Zookeeper實例正在於Zookeeper服務器創建鏈接時,是處於CONNECTING狀態的。一旦鏈接創建好之後,他就變成了Connected狀態。

使用Zookeeper的客戶端能夠經過註冊Watcher的方法來獲取狀態轉變的消息。一旦進入了CONNNECTED狀態,Watcher將得到一個KeepState值爲SyncConnected的WatchedEvent。

注意Zookeeper的watcher有兩個職責:

<1>瞭解Zookeeper的狀態改變。傳遞給ZooKeeper對象構造函數的(默認)watcher,被用來監測狀態的改變。

<2>瞭解Zonde的改變。監測Zonde的改變既可使用專門的實例設置到讀操做上,也可使用讀操做的默認watcher。

Zookeeper實例可能失去或從新鏈接Zookeeper服務,在CONNECTED和CONNECTING狀態中切換。若是鏈接斷開,watcher獲得一個Disconnected事件。學要注意的是,這些狀態的遷移是由Zookeeper實例本身發起的,若是鏈接斷開他將自動嘗試自動鏈接。

若是任何一個close()方法被調用,或是會話由Expired類型的KeepState提示過時時,ZooKeeper可能會轉變成第三種狀態CLOSED。一旦處於CLOSED狀態,Zookeeper對象將再也不是活動的了(可使用states的isActive()方法進行測試),並且不能被重用。客戶端必須創建一個新的Zookeeper實例才能從新鏈接到Zookeeper服務。

下期預告:ZooKeeper的集羣安裝和配置,敬請關注。本期內容及供你們參考,有什麼不對的地方,但願你們給予指點更正。若是您以爲,文章寫得還行,就擡起您的貴手,點一下推薦

相關文章
相關標籤/搜索