Zookeeper 分布式服務架構是 Apache Hadoop 的一個子項目,它主要是用來解決分布式應用中經常遇到的一些資料管理問題,如:統一命名服務、狀态同步服務、叢集管理、分布式應用配置項的管理等。本文将從使用者角度詳細介紹 Zookeeper 的安裝和配置檔案中各個配置項的意義,以及分析 Zookeeper 的典型的應用場景(配置檔案的管理、叢集管理、同步鎖、Leader 選舉、隊列管理等),用 Java 實作它們并給出示例代碼。
單機安裝非常簡單,隻要擷取到 Zookeeper 的壓縮包并解壓到某個目錄如:/home/zookeeper-3.2.2 下,Zookeeper 的啟動腳本在 bin 目錄下,Linux 下的啟動腳本是 zkServer.sh,在 3.2.2 這個版本 Zookeeper 沒有提供 windows 下的啟動腳本,是以要想在 windows 下啟動 Zookeeper 要自己手工寫一個,如清單 1 所示:
在你執行啟動腳本之前,還有幾個基本的配置項需要配置一下,Zookeeper 的配置檔案在 conf 目錄下,這個目錄下有 zoo_sample.cfg 和 log4j.properties,你需要做的就是将 zoo_sample.cfg 改名為 zoo.cfg,因為 Zookeeper 在啟動時會找這個檔案作為預設配置檔案。下面詳細介紹一下,這個配置檔案中各個配置項的意義。
tickTime:這個時間是作為 Zookeeper 伺服器之間或用戶端與伺服器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
dataDir:顧名思義就是 Zookeeper 儲存資料的目錄,預設情況下,Zookeeper 将寫資料的日志檔案也儲存在這個目錄裡。
clientPort:這個端口就是用戶端連接配接 Zookeeper 伺服器的端口,Zookeeper 會監聽這個端口,接受用戶端的通路請求。
當這些配置項配置好後,你現在就可以啟動 Zookeeper 了,啟動後要檢查 Zookeeper 是否已經在服務,可以通過 netstat – ano 指令檢視是否有你配置的 clientPort 端口号在監聽服務。
Zookeeper 不僅可以單機提供服務,同時也支援多機組成叢集來提供服務。實際上 Zookeeper 還支援另外一種僞叢集的方式,也就是可以在一台實體機上運作多個 Zookeeper 執行個體,下面将介紹叢集模式的安裝和配置。
Zookeeper 的叢集模式的安裝和配置也不是很複雜,所要做的就是增加幾個配置項。叢集模式除了上面的三個配置項還要增加下面幾個配置項:
initLimit:這個配置項是用來配置 Zookeeper 接受用戶端(這裡所說的用戶端不是使用者連接配接 Zookeeper 伺服器的用戶端,而是 Zookeeper 伺服器叢集中連接配接到 Leader 的 Follower 伺服器)初始化連接配接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper 伺服器還沒有收到用戶端的傳回資訊,那麼表明這個用戶端連接配接失敗。總的時間長度就是 5*2000=10 秒
syncLimit:這個配置項辨別 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾号伺服器;B 是這個伺服器的 ip 位址;C 表示的是這個伺服器與叢集中的 Leader 伺服器交換資訊的端口;D 表示的是萬一叢集中的 Leader 伺服器挂了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時伺服器互相通信的端口。如果是僞叢集的配置方式,由于 B 都是一樣,是以不同的 Zookeeper 執行個體通信端口号不能一樣,是以要給它們配置設定不同的端口号。
除了修改 zoo.cfg 配置檔案,叢集模式下還要配置一個檔案 myid,這個檔案在 dataDir 目錄下,這個檔案裡面就有一個資料就是 A 的值,Zookeeper 啟動時會讀取這個檔案,拿到裡面的資料與 zoo.cfg 裡面的配置資訊比較進而判斷到底是那個 server。
Zookeeper 會維護一個具有層次關系的資料結構,它非常類似于一個标準的檔案系統,如圖 1 所示:
Zookeeper 這種資料結構有如下這些特點:
每個子目錄項如 NameService 都被稱作為 znode,這個 znode 是被它所在的路徑唯一辨別,如 Server1 這個 znode 的辨別為 /NameService/Server1
znode 可以有子節點目錄,并且每個 znode 可以存儲資料,注意 EPHEMERAL 類型的目錄節點不能有子節點目錄
znode 是有版本的,每個 znode 中存儲的資料可以有多個版本,也就是一個通路路徑中可以存儲多份資料
znode 可以是臨時節點,一旦建立這個 znode 的用戶端與伺服器失去聯系,這個 znode 也将自動删除,Zookeeper 的用戶端和伺服器通信采用長連接配接方式,每個用戶端和伺服器通過心跳來保持連接配接,這個連接配接狀态稱為 session,如果 znode 是臨時節點,這個 session 失效,znode 也就删除了
znode 的目錄名可以自動編号,如 App1 已經存在,再建立的話,将會自動命名為 App2
znode 可以被監控,包括這個目錄節點中存儲的資料的修改,子節點目錄的變化等,一旦變化可以通知設定監控的用戶端,這個是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于這個特性實作的,後面在典型的應用場景中會有執行個體介紹
<a href="http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/#ibm-pcon">回頁首</a>
Zookeeper 作為一個分布式的服務架構,主要用來解決分布式叢集中應用系統的一緻性問題,它能提供基于類似于檔案系統的目錄節點樹方式的資料存儲,但是 Zookeeper 并不是用來專門存儲資料的,它的作用主要是用來維護和監控你存儲的資料的狀态變化。通過監控這些資料狀态的變化,進而可以達到基于資料的叢集管理,後面将會詳細介紹 Zookeeper 能夠解決的一些典型問題,這裡先介紹一下,Zookeeper 的操作接口和簡單使用示例。
用戶端要連接配接 Zookeeper 伺服器可以通過建立 org.apache.zookeeper. ZooKeeper 的一個執行個體對象,然後調用這個類提供的接口來和伺服器互動。
前面說了 ZooKeeper 主要是用來維護和監控一個目錄節點樹中存儲的資料的狀态,所有我們能夠操作 ZooKeeper 的也和操作目錄節點樹大體一樣,如建立一個目錄節點,給某個目錄節點設定資料,擷取某個目錄節點的所有子目錄節點,給某個目錄節點設定權限和監控這個目錄節點的狀态變化。
這些接口如下表所示:
方法名
方法功能描述
重載方法,這裡給某個目錄節點設定特定的 watcher,Watcher 在 ZooKeeper 是一個核心功能,Watcher 可以監控目錄節點的資料變化以及子目錄的變化,一旦這些狀态發生變化,伺服器就會通知所有設定在這個目錄節點上的 Watcher,進而每個用戶端都很快知道它所關注的目錄節點的狀态發生變化,而做出相應的反應
删除 path 對應的目錄節點,version 為 -1 可以比對任何版本,也就删除了這個目錄節點所有資料
給 path 設定資料,可以指定這個資料的版本号,如果 version 為 -1 怎可以比對任何版本
擷取這個 path 對應的目錄節點存儲的資料,資料的版本等資訊可以通過 stat 來指定,同時還可以設定是否監控這個目錄節點資料的狀态
用戶端将自己的授權資訊送出給伺服器,伺服器将根據這個授權資訊驗證用戶端的通路權限。
給某個目錄節點重新設定通路權限,需要注意的是 Zookeeper 中的目錄節點權限不具有傳遞性,父目錄節點的權限不能傳遞給子目錄節點。目錄節點 ACL 由兩部分組成:perms 和 id。
Perms 有 ALL、READ、WRITE、CREATE、DELETE、ADMIN 幾種
而 id 辨別了通路目錄節點的身份清單,預設情況下有以下兩種:
ANYONE_ID_UNSAFE = new Id("world", "anyone") 和 AUTH_IDS = new Id("auth", "") 分别表示任何人都可以通路和建立者擁有通路權限。
擷取某個目錄節點的通路權限清單
除了以上這些上表中列出的方法之外還有一些重載方法,如都提供了一個回調類的重載方法以及可以設定特定 Watcher 的重載方法,具體的方法可以參考 org.apache.zookeeper. ZooKeeper 類的 API 說明。
下面給出基本的操作 ZooKeeper 的示例代碼,這樣你就能對 ZooKeeper 有直覺的認識了。下面的清單包括了建立與 ZooKeeper 伺服器的連接配接以及最基本的資料操作:
輸出的結果如下:
當對目錄節點監控狀态打開時,一旦目錄節點的狀态發生變化,Watcher 對象的 process 方法就會被調用。
Zookeeper 從設計模式角度來看,是一個基于觀察者模式設計的分布式服務管理架構,它負責存儲和管理大家都關心的資料,然後接受觀察者的注冊,一旦這些資料的狀态發生變化,Zookeeper 就将負責通知已經在 Zookeeper 上注冊的那些觀察者做出相應的反應,進而實作叢集中類似 Master/Slave 管理模式,關于 Zookeeper 的詳細架構等内部細節可以閱讀 Zookeeper 的源碼
下面詳細介紹這些典型的應用場景,也就是 Zookeeper 到底能幫我們解決那些問題?下面将給出答案。
分布式應用中,通常需要有一套完整的命名規則,既能夠産生唯一的名稱又便于人識别和記住,通常情況下用樹形的名稱結構是一個理想的選擇,樹形的名稱結構是一個有層次的目錄結構,既對人友好又不會重複。說到這裡你可能想到了 JNDI,沒錯 Zookeeper 的 Name Service 與 JNDI 能夠完成的功能是差不多的,它們都是将有層次的目錄結構關聯到一定資源上,但是 Zookeeper 的 Name Service 更加是廣泛意義上的關聯,也許你并不需要将名稱關聯到特定資源上,你可能隻需要一個不會重複名稱,就像資料庫中産生一個唯一的數字主鍵一樣。
Name Service 已經是 Zookeeper 内置的功能,你隻要調用 Zookeeper 的 API 就能實作。如調用 create 接口就可以很容易建立一個目錄節點。
配置的管理在分布式應用環境中很常見,例如同一個應用系統需要多台 PC Server 運作,但是它們運作的應用系統的某些配置項是相同的,如果要修改這些相同的配置項,那麼就必須同時修改每台運作這個應用系統的 PC Server,這樣非常麻煩而且容易出錯。
像這樣的配置資訊完全可以交給 Zookeeper 來管理,将配置資訊儲存在 Zookeeper 的某個目錄節點中,然後将所有需要修改的應用機器監控配置資訊的狀态,一旦配置資訊發生變化,每台應用機器就會收到 Zookeeper 的通知,然後從 Zookeeper 擷取新的配置資訊應用到系統中。
Zookeeper 能夠很容易的實作叢集管理的功能,如有多台 Server 組成一個服務叢集,那麼必須要一個“總管”知道目前叢集中每台機器的服務狀态,一旦有機器不能提供服務,叢集中其它叢集必須知道,進而做出調整重新配置設定服務政策。同樣當增加叢集的服務能力時,就會增加一台或多台 Server,同樣也必須讓“總管”知道。
Zookeeper 不僅能夠幫你維護目前的叢集中機器的服務狀态,而且能夠幫你選出一個“總管”,讓這個總管來管理叢集,這就是 Zookeeper 的另一個功能 Leader Election。
Zookeeper 如何實作 Leader Election,也就是選出一個 Master Server。和前面的一樣每台 Server 建立一個 EPHEMERAL 目錄節點,不同的是它還是一個 SEQUENTIAL 目錄節點,是以它是個 EPHEMERAL_SEQUENTIAL 目錄節點。之是以它是 EPHEMERAL_SEQUENTIAL 目錄節點,是因為我們可以給每台 Server 編号,我們可以選擇目前是最小編号的 Server 為 Master,假如這個最小編号的 Server 死去,由于是 EPHEMERAL 節點,死去的 Server 對應的節點也被删除,是以目前的節點清單中又出現一個最小編号的節點,我們就選擇這個節點為目前 Master。這樣就實作了動态選擇 Master,避免了傳統意義上單 Master 容易出現單點故障的問題。
這部分的示例代碼如下,完整的代碼請看附件:
同步鎖的實作代碼如下,完整的代碼請看附件:
Zookeeper 可以處理兩種類型的隊列:
當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達,這種是同步隊列。
隊列按照 FIFO 方式進行入隊和出隊操作,例如實作生産者和消費者模型。
同步隊列用 Zookeeper 實作的實作思路如下:
建立一個父目錄 /synchronizing,每個成員都監控标志(Set Watch)位目錄 /synchronizing/start 是否存在,然後每個成員都加入這個隊列,加入隊列的方式就是建立 /synchronizing/member_i 的臨時目錄節點,然後每個成員擷取 / synchronizing 目錄的所有目錄節點,也就是 member_i。判斷 i 的值是否已經是成員的個數,如果小于成員個數等待 /synchronizing/start 的出現,如果已經相等就建立 /synchronizing/start。
用下面的流程圖更容易了解:
同步隊列的關鍵代碼如下,完整的代碼請看附件:
當隊列沒滿是進入 wait(),然後會一直等待 Watch 的通知,Watch 的代碼如下:
FIFO 隊列用 Zookeeper 實作思路如下:
實作的思路也非常簡單,就是在特定的目錄下建立 SEQUENTIAL 類型的子目錄 /queue_i,這樣就能保證所有成員加入隊列時都是有編号的,出隊列時通過 getChildren( ) 方法可以傳回目前所有的隊列中的元素,然後消費其中最小的一個,這樣就能保證 FIFO。
下面是生産者和消費者這種隊列形式的示例代碼,完整的代碼請看附件:
Zookeeper 作為 Hadoop 項目中的一個子項目,是 Hadoop 叢集管理的一個必不可少的子產品,它主要用來控制叢集中的資料,如它管理 Hadoop 叢集中的 NameNode,還有 Hbase 中 Master Election、Server 之間狀态同步等。
本文介紹的 Zookeeper 的基本知識,以及介紹了幾個典型的應用場景。這些都是 Zookeeper 的基本功能,最重要的是 Zoopkeeper 提供了一套很好的分布式叢集管理的機制,就是它這種基于層次型的目錄樹的資料結構,并對樹中的節點進行有效管理,進而可以設計出多種多樣的分布式的資料管理模型,而不僅僅局限于上面提到的幾個常用應用場景。
描述
名字
大小
樣例代碼
<a href="http://www.ibm.com/developerworks/apps/download/index.jsp?contentid=587933&filename=sample.rar&method=http&locale=zh_CN">sample.rar</a>
8KB
http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/p/6363939.html,如需轉載請自行聯系原作者