天天看點

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

單機安裝非常簡單,隻要擷取到 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 所示:

<a>圖 1 zookeeper 資料結構</a>

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

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 的很多功能都是基于這個特性實作的,後面在典型的應用場景中會有執行個體介紹

zookeeper 作為一個分布式的服務架構,主要用來解決分布式叢集中應用系統的一緻性問題,它能提供基于類似于檔案系統的目錄節點樹方式的資料存儲,但是 zookeeper 并不是用來專門存儲資料的,它的作用主要是用來維護和監控你存儲的資料的狀态變化。通過監控這些資料狀态的變化,進而可以達到基于資料的叢集管理,後面将會詳細介紹 zookeeper 能夠解決的一些典型問題,這裡先介紹一下,zookeeper 的操作接口和簡單使用示例。

用戶端要連接配接 zookeeper 伺服器可以通過建立 org.apache.zookeeper. zookeeper 的一個執行個體對象,然後調用這個類提供的接口來和伺服器互動。

前面說了 zookeeper 主要是用來維護和監控一個目錄節點樹中存儲的資料的狀态,所有我們能夠操作 zookeeper 的也和操作目錄節點樹大體一樣,如建立一個目錄節點,給某個目錄節點設定資料,擷取某個目錄節點的所有子目錄節點,給某個目錄節點設定權限和監控這個目錄節點的狀态變化。

這些接口如下表所示:

方法名

方法功能描述

1,然後傳回給用戶端已經成功建立的目錄節點名;ephemeral:臨時目錄節點,一旦建立這個節點的用戶端與伺服器端口也就是 session 逾時,這種節點會被自動删除;ephemeral_sequential:臨時自動編号節點

boolean watch)

重載方法,這裡給某個目錄節點設定特定的 watcher,watcher 在 zookeeper 是一個核心功能,watcher 可以監控目錄節點的資料變化以及子目錄的變化,一旦這些狀态發生變化,伺服器就會通知所有設定在這個目錄節點上的 watcher,進而每個用戶端都很快知道它所關注的目錄節點的狀态發生變化,而做出相應的反應

删除 path 對應的目錄節點,version 為 -1 可以比對任何版本,也就删除了這個目錄節點所有資料

byte[] data, int version)

給 path 設定資料,可以指定這個資料的版本号,如果 version 為 -1 怎可以比對任何版本

擷取這個 path 對應的目錄節點存儲的資料,資料的版本等資訊可以通過 stat 來指定,同時還可以設定是否監控這個目錄節點資料的狀态

用戶端将自己的授權資訊送出給伺服器,伺服器将根據這個授權資訊驗證用戶端的通路權限。

int version)

給某個目錄節點重新設定通路權限,需要注意的是 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 擷取新的配置資訊應用到系統中。

<a>圖 2. 配置管理結構圖</a>

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

zookeeper 能夠很容易的實作叢集管理的功能,如有多台 server 組成一個服務叢集,那麼必須要一個“總管”知道目前叢集中每台機器的服務狀态,一旦有機器不能提供服務,叢集中其它叢集必須知道,進而做出調整重新配置設定服務政策。同樣當增加叢集的服務能力時,就會增加一台或多台 server,同樣也必須讓“總管”知道。

zookeeper 不僅能夠幫你維護目前的叢集中機器的服務狀态,而且能夠幫你選出一個“總管”,讓這個總管來管理叢集,這就是 zookeeper 的另一個功能 leader election。

watch 将會被調用,是以其它 server 就知道已經有某台 server 死去了。新增 server 也是同樣的原理。

zookeeper 如何實作 leader election,也就是選出一個 master server。和前面的一樣每台 server 建立一個 ephemeral 目錄節點,不同的是它還是一個 sequential 目錄節點,是以它是個 ephemeral_sequential 目錄節點。之是以它是 ephemeral_sequential 目錄節點,是因為我們可以給每台 server 編号,我們可以選擇目前是最小編号的 server 為 master,假如這個最小編号的 server 死去,由于是

ephemeral 節點,死去的 server 對應的節點也被删除,是以目前的節點清單中又出現一個最小編号的節點,我們就選擇這個節點為目前 master。這樣就實作了動态選擇 master,避免了傳統意義上單 master 容易出現單點故障的問題。

<a>圖 3. 叢集管理結構圖</a>

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

這部分的示例代碼如下,完整的代碼請看附件:

<a>清單 3. leader election 關鍵代碼</a>

boolean watch) 方法并監控 zookeeper 上目錄節點清單的變化,一直到自己建立的節點是清單中最小編号的目錄節點,進而獲得鎖,釋放鎖很簡單,隻要删除前面它自己所建立的目錄節點就行了。

<a>圖 4. zookeeper 實作 locks 的流程圖</a>

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

同步鎖的實作代碼如下,完整的代碼請看附件:

<a>清單 4. 同步鎖的關鍵代碼</a>

zookeeper 可以處理兩種類型的隊列:

當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達,這種是同步隊列。

隊列按照 fifo 方式進行入隊和出隊操作,例如實作生産者和消費者模型。

同步隊列用 zookeeper 實作的實作思路如下:

建立一個父目錄 /synchronizing,每個成員都監控标志(set watch)位目錄 /synchronizing/start 是否存在,然後每個成員都加入這個隊列,加入隊列的方式就是建立 /synchronizing/member_i 的臨時目錄節點,然後每個成員擷取 / synchronizing 目錄的所有目錄節點,也就是 member_i。判斷 i 的值是否已經是成員的個數,如果小于成員個數等待 /synchronizing/start 的出現,如果已經相等就建立 /synchronizing/start。

用下面的流程圖更容易了解:

<a>圖 5. 同步隊列流程圖</a>

分布式服務架構 Zookeeper -- 管理分布式環境中的資料安裝和配置詳解如何使用ZooKeeper 典型的應用場景總結轉載

同步隊列的關鍵代碼如下,完整的代碼請看附件:

<a>清單 5. 同步隊列</a>

當隊列沒滿是進入 wait(),然後會一直等待 watch 的通知,watch 的代碼如下:

fifo 隊列用 zookeeper 實作思路如下:

實作的思路也非常簡單,就是在特定的目錄下建立 sequential 類型的子目錄 /queue_i,這樣就能保證所有成員加入隊列時都是有編号的,出隊列時通過 getchildren( ) 方法可以傳回目前所有的隊列中的元素,然後消費其中最小的一個,這樣就能保證 fifo。

下面是生産者和消費者這種隊列形式的示例代碼,完整的代碼請看附件:

<a>清單 6. 生産者代碼</a>

<a>清單 7. 消費者代碼</a>

zookeeper 作為 hadoop 項目中的一個子項目,是 hadoop 叢集管理的一個必不可少的子產品,它主要用來控制叢集中的資料,如它管理 hadoop 叢集中的 namenode,還有 hbase 中 master election、server 之間狀态同步等。

本文介紹的 zookeeper 的基本知識,以及介紹了幾個典型的應用場景。這些都是 zookeeper 的基本功能,最重要的是 zoopkeeper 提供了一套很好的分布式叢集管理的機制,就是它這種基于層次型的目錄樹的資料結構,并對樹中的節點進行有效管理,進而可以設計出多種多樣的分布式的資料管理模型,而不僅僅局限于上面提到的幾個常用應用場景。

<a target="_blank" href="http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/">url</a>

上一篇: Fast Paxos

繼續閱讀