zookeeper 快速入門

分佈式系統簡介

在分佈式系統中另外一個須要解決的重要問題就是數據的複製。咱們平常開發中,不少人會碰到一個問題:客戶端C1更新了一個值K1由V1更新到V2.可是客戶端C2沒法當即讀取到K的最新值。上面的例子就是常見的數據庫之間複製的延時問題。html

分佈式系統對於數據的複製通常因爲:java

  1. 爲了增長系統的可用性,以防止單點故障引發的系統不可用。
  2. 提升系統的總體性能,經過負載均衡,可以讓分佈在不一樣地方的數據副本都可以爲用戶提供服務。

爲了解決複製延時的問題,能夠等待全部複製都完成後,在進行下一次更新,但這會帶來性能問題。
爲了保證數據一致性,同時又不能影響系統運行的性能,因而,一致性級別由此誕生。node

  • 強一致性: 系統寫入什麼,讀出來就是什麼,對系統的性能影響比較大。
  • 弱一致性: 系統在寫入後,不承諾當即能夠讀取寫入的值,但會盡量的保證在某個時間級別後,達到一致性狀態。
    • 會話一致性: 對於寫入的值,同一個客戶端會話中能夠讀取到一致的值。
    • 用戶一致性: 對於寫入的值,在同一個用戶中能夠讀取到一致性的值,其餘用戶不能保證。
  • 最終一致性:跟弱一致性中很是重要的一種一致性模型,也是業界在大型分佈式系統的數據一致性上比較推崇的模型。

zookeeper 產生的緣由

Zookeeper是Hadoop分佈式調度服務,用來構建分佈式應用系統。構建一個分佈式應用是一個很複雜的事情,主要的緣由是咱們須要合理有效的處理分佈式集羣中的部分失敗的問題。例如,集羣中的節點在相互通訊時,A節點向B節點發送消息。A節點若是想知道消息是否發送成功,只能由B節點告訴A節點。那麼若是B節點關機或者因爲其餘的緣由脫離集羣網絡,問題就出現了。A節點不斷的向B發送消息,而且沒法得到B的響應。B也沒有辦法通知A節點已經離線或者關機。集羣中其餘的節點徹底不知道B發生了什麼狀況,還在不斷的向B發送消息。這時,你的整個集羣就發生了部分失敗的故障。git

Zookeeper不能讓部分失敗的問題完全消失,可是它提供了一些工具可以讓你的分佈式應用安全合理的處理部分失敗的問題。github

zookeeper工做原理

Zookeeper 的核心是廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫作Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播 模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步之後, 恢復模式就結束了。狀態同步保證了leader和Server具備相同的系統狀態。爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號 (zxid)來標識事務。全部的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用 來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞 增計數。算法

zab協議核心內容

zab協議的核心是定義了對於那些會改變zookeeper服務器數據狀態的事務請求的處理方式,即:全部事務請求必須由一個全局惟一的服務器來協調處理,這樣的服務器被稱爲Leader服務器,而餘下的其餘服務器則成爲Follower服務器。Leader服務器負責將一個客戶端事務請求轉換成一個事務Proposal(提倡),並將該Proposal分發給集羣中全部的Follower 服務器。以後Leader服務器須要等待全部Follower服務器的反饋,一旦超過半數的Follower服務器進行了正確的反饋後,那麼Leader就會再次向全部的Follower服務器分發Commit消息,要求將其前一個Proposal進行提交。

每一個Server在工做過程當中有三種狀態:

  • LOOKING:當前Server不知道leader是誰,正在搜尋。
  • LEADING:當前Server即爲選舉出來的leader。
  • FOLLOWING:leader已經選舉出來,當前Server與之同步。

每一個集羣中的三種狀態

  • Leader : 爲客戶端提供讀和寫服務。
  • Follower: 爲客戶端提供讀服務。
  • observer: 爲客戶端提供讀服務,可是不參與Leader選舉,也不參與寫操做的「過辦寫成功」策略。因此 observer能夠在不影響寫性能的狀況下提高集羣的讀性能。

zookeeper 特性

  1. 順序一致性:從同一個客戶端發起的事務請求,最終將嚴格按照其發起順序被應用到ZooKeeper中。
  2. 原子性:更新操做要麼成功要麼失敗,沒有中間狀態。
  3. 單一視圖(Single system image):無論客戶端鏈接哪個服務器,客戶端看到服務端的數據模型都是一致的(the same view of service)。
  4. 可靠性(Reliability): 一旦一個更新成功,那麼那就會被持久化,直到客戶端用新的更新覆蓋這個更新。
  5. 實時性(Timeliness):Zookeeper僅保證在必定時間內,客戶端最終必定可以從服務端讀到最新的數據狀態。

基本概念

zookeeper數據模型

Zookeeper 會維護一個具備層次關係的數據結構,它很是相似於一個標準的文件系統. 名稱叫作zNode。shell

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 的不少功能都是基於這個特性實現的。

Node能夠分爲持久節點(PERSISTENT)和臨時節點(EPHEMERAL)兩類。所謂持久節點是指一旦這個 ZNode被建立了,除非主動進行移除操做,不然這個節點將一直保存在 Zookeeper上。而臨時節點的生命週期,是與客戶端會話綁定的,一旦客戶端會話失效,那麼這個客戶端建立的全部臨時節點都會被移除。
另外,Zookeeper還有一種 順序節點(SEQUENTIAL)。該節點被建立的時候,Zookeeper會自動在其子節點名上,加一個由父節點維護的、自增整數的後綴 (上限: Integer.MAX_VALUE)。該節點的特性,還能夠應用到 持久/臨時節點 上,組合成 持久順序節點 (PERSISTENT_SEQUENTIAL) 和 臨時順序節點 ( EPHEMERAL_SEQUENTIAL)apache

會話

Session指客戶端會話。在 Zookeeper中,一個客戶端會話是指 客戶端和服務器之間的一個TCP長鏈接。客戶端啓動的時候,會與服務端創建一個TCP鏈接,客戶端會話的生命週期,則是從第一次鏈接創建開始算起。經過這個鏈接,客戶端可以經過心跳檢測與服務器保持有效的會話,並向 Zookeeper服務器發送請求並接收響應,以及接收來自服務端的 Watch事件通知。vim

Session的 sessionTimeout參數,用來控制一個客戶端會話的超時時間。當服務器壓力太大 或者是網絡故障等各類緣由致使客戶端鏈接斷開時,Client會自動從 Zookeeper地址列表中逐一嘗試重連 (重試策略可以使用 Curator來實現)。只要在 sessionTimeout規定的時間內可以從新鏈接上集羣中任意一臺服務器,那麼以前建立的會話仍然有效。若是,在 sessionTimeout時間外重連了,就會由於 session已經被清除了,而被告知 SESSION_EXPIRED,此時須要程序去恢復臨時數據;還有一種 Session重建後的在新節點上的數據,被以前節點上因網絡延遲晚來的寫請求所覆蓋的狀況,在 ZOOKEEPER-417中被提出,並在該 JIRA中新加入的 SessionMovedException,使得 用同一個sessionld/sessionPasswd 重建 Session的客戶端能感知到,可是這個問題到 ZOOKEEPER-2219仍然沒有獲得很好的解決。

版本

Zookeeper的每一個 ZNode上都會存儲數據,對應於每一個 ZNode,Zookeeper都會爲其維護一個叫作 Stat的數據結構,Stat中記錄了這個 ZNode的三個數據版本,分別是 version(當前 ZNode數據內容的版本),cversion(當前 ZNode子節點的版本)和 aversion (當前 ZNode的 ACL變動版本)。這裏的版本起到了控制 Zookeeper操做原子性的做用 (詳見 「源碼分析 - 落腳點 - Zookeeper樂觀鎖」)

watch

Watcher(事件監聽器)是 Zookeeper提供的一種 發佈/訂閱的機制。Zookeeper容許用戶在指定節點上註冊一些 Watcher,而且在一些特定事件觸發的時候,Zookeeper服務端會將事件通知給訂閱的客戶端。該機制是 Zookeeper實現分佈式協調的重要特性

ACL

相似於 Unix文件系統,Zookeeper採用 ACL(Access Control Lists)策略來進行權限控制 (使用格式
setAcl <path> <acl: scheme + id + permissions>)。
例子:

setAcl /zk world:anyone:cdrw
  • CREATE (c): 建立子節點的權限。
  • READ (r): 獲取節點數據和子節點列表的權限。
  • WRITE (w): 更新節點數據的權限。
  • DELETE (d): 刪除當前節點的權限。
  • ADMIN (a): 管理權限,能夠設置當前節點的permission。
scheme ID comment
world anyone Zookeeper中對全部人有權限的結點就是屬於 world:anyone
auth 不須要id 經過 authentication的 user都有權限
digest username:BASE64 (SHA1(password)) 須要先經過 username:password形式的 authentication
ip id爲客戶機的IP地址(或者 IP地址段) ip:192.168.1.0/14,表示匹配前 14個bit的 IP段
super 對應的 id擁有超級權限 (CRWDA)

Zookeeper支持經過 kerberos來進行 authencation,也支持 username/password形式的 authentication。

ZooKeeper 典型的應用場景

Zookeeper 做爲一個分佈式的服務框架,主要用來解決分佈式集羣中應用系統的一致性問題,它能提供基於相似於文件系統的目錄節點樹方式的數據存儲,可是 Zookeeper 並非用來專門存儲數據的,它的做用主要是用來維護和監控你存儲的數據的狀態變化。經過監控這些數據狀態的變化,從而能夠達到基於數據的集羣管理。

Zookeeper 從設計模式角度來看,是一個基於觀察者模式設計的分佈式服務管理框架,它負責存儲和管理你們都關心的數據,而後接受觀察者的註冊,一旦這些數據的狀態發生變化,Zookeeper 就將負責通知已經在 Zookeeper 上註冊的那些觀察者作出相應的反應,從而實現集羣中相似 Master/Slave 管理模式,關於 Zookeeper 的詳細架構等內部細節能夠閱讀 Zookeeper 的源碼

統一命名服務(Name Service)

分佈式應用中,一般須要有一套完整的命名規則,既可以產生惟一的名稱又便於人識別和記住,一般狀況下用樹形的名稱結構是一個理想的選擇,樹形的名稱結構是一個有層次的目錄結構,既對人友好又不會重複。說到這裏你可能想到了 JNDI,沒錯 Zookeeper 的 Name Service 與 JNDI 可以完成的功能是差很少的,它們都是將有層次的目錄結構關聯到必定資源上,可是 Zookeeper 的 Name Service 更加是普遍意義上的關聯,也許你並不須要將名稱關聯到特定資源上,你可能只須要一個不會重複名稱,就像數據庫中產生一個惟一的數字主鍵同樣。
Name Service 已是 Zookeeper 內置的功能,你只要調用 Zookeeper 的 API 就能實現。如調用 create 接口就能夠很容易建立一個目錄節點。

配置管理(Configuration Management)

配置的管理在分佈式應用環境中很常見,例如同一個應用系統須要多臺 PC Server 運行,可是它們運行的應用系統的某些配置項是相同的,若是要修改這些相同的配置項,那麼就必須同時修改每臺運行這個應用系統的 PC Server,這樣很是麻煩並且容易出錯。
像這樣的配置信息徹底能夠交給 Zookeeper 來管理,將配置信息保存在 Zookeeper 的某個目錄節點中,而後將全部須要修改的應用機器監控配置信息的狀態,一旦配置信息發生變化,每臺應用機器就會收到 Zookeeper 的通知,而後從 Zookeeper 獲取新的配置信息應用到系統中。

集羣管理(Group Membership)

Zookeeper 可以很容易的實現集羣管理的功能,若有多臺 Server 組成一個服務集羣,那麼必需要一個「總管」知道當前集羣中每臺機器的服務狀態,一旦有機器不能提供服務,集羣中其它集羣必須知道,從而作出調整從新分配服務策略。一樣當增長集羣的服務能力時,就會增長一臺或多臺 Server,一樣也必須讓「總管」知道。
Zookeeper 不只可以幫你維護當前的集羣中機器的服務狀態,並且可以幫你選出一個「總管」,讓這個總管來管理集羣,這就是 Zookeeper 的另外一個功能 Leader Election。
它們的實現方式都是在 Zookeeper 上建立一個 EPHEMERAL 類型的目錄節點,而後每一個 Server 在它們建立目錄節點的父目錄節點上調用 getChildren(String path, boolean watch) 方法並設置 watch 爲 true,因爲是 EPHEMERAL 目錄節點,當建立它的 Server 死去,這個目錄節點也隨之被刪除,因此 Children 將會變化,這時 getChildren上的 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 容易出現單點故障的問題。

集羣管理結構圖

共享鎖(Locks)

共享鎖在同一個進程中很容易實現,可是在跨進程或者在不一樣 Server 之間就很差實現了。Zookeeper 卻很容易實現這個功能,實現方式也是須要得到鎖的 Server 建立一個 EPHEMERAL_SEQUENTIAL 目錄節點,而後調用 getChildren方法獲取當前的目錄節點列表中最小的目錄節點是否是就是本身建立的目錄節點,若是正是本身建立的,那麼它就得到了這個鎖,若是不是那麼它就調用 exists(String path, boolean watch) 方法並監控 Zookeeper 上目錄節點列表的變化,一直到本身建立的節點是列表中最小編號的目錄節點,從而得到鎖,釋放鎖很簡單,只要刪除前面它本身所建立的目錄節點就好了。

Zookeeper 實現 Locks 的流程圖

隊列管理

Zookeeper 能夠處理兩種類型的隊列:
當一個隊列的成員都聚齊時,這個隊列纔可用,不然一直等待全部成員到達,這種是同步隊列。
隊列按照 FIFO 方式進行入隊和出隊操做,例如實現生產者和消費者模型。
同步隊列用 Zookeeper 實現的實現思路以下:
建立一個父目錄 /synchronizing,每一個成員都監控標誌(Set Watch)位目錄 /synchronizing/start 是否存在,而後每一個成員都加入這個隊列,加入隊列的方式就是建立 /synchronizing/member_i 的臨時目錄節點,而後每一個成員獲取 / synchronizing 目錄的全部目錄節點,也就是 member_i。判斷 i 的值是否已是成員的個數,若是小於成員個數等待 /synchronizing/start 的出現,若是已經相等就建立 /synchronizing/start。
用下面的流程圖更容易理解:

同步隊列流程圖
FIFO 隊列用 Zookeeper 實現思路以下:
實現的思路也很是簡單,就是在特定的目錄下建立 SEQUENTIAL 類型的子目錄 /queue_i,這樣就能保證全部成員加入隊列時都是有編號的,出隊列時經過 getChildren( ) 方法能夠返回當前全部的隊列中的元素,而後消費其中最小的一個,這樣就能保證 FIFO。

zookeeper安裝

zookeeper 集羣分爲:單機模式,僞集羣,集羣模式。

zookeeper配置文件解釋

單機模式下須要修改的配置

tickTime=2000  
dataDir=/data/zk 
dataLogDir=/var/log/zookeeper/logs  
clientPort=2181
  • tickTime(CS通訊心跳數): Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每一個 tickTime 時間就會發送一個心跳。tickTime以毫秒爲單位。
  • dataDir(數據文件目錄):Zookeeper保存數據的目錄,默認狀況下,Zookeeper將寫數據的日誌文件也保存在這個目錄裏。
  • dataLogDir(日誌文件目錄):Zookeeper保存事務日誌文件的目錄。若是沒有配置則存放在dataDir目錄下。
  • clientPort(客戶端鏈接端口):客戶端鏈接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。

集羣模式下須要增長的配置

initLimit=5  
syncLimit=2  
server.N=YYY:A:B
  • initLimit(LF初始通訊時限): 集羣中的follower服務器(F)與leader服務器(L)之間初始鏈接時能容忍的最多心跳數(tickTime的數量)。
  • syncLimit(LF同步通訊時限): 集羣中的follower服務器與leader服務器之間請求和應答之間能容忍的最多心跳數(tickTime的數量)。
  • server.N=YYY:A:B(服務器名稱與地址:集羣信息(服務器編號,服務器地址,LF通訊端口,選舉端口): 這個配置項的書寫格式比較特殊,規則以下:

其中N表示服務器編號,YYY表示服務器的IP地址,A爲LF通訊端口,表示該服務器與集羣中的leader交換的信息的端口。B爲選舉端口,表示選舉新leader時服務器間相互通訊的端口(當leader掛掉時,其他服務器會相互通訊,選擇出新的leader)。通常來講,集羣中每一個服務器的A端口都是同樣,每一個服務器的B端口也是同樣。可是當所採用的爲僞集羣時,IP地址都同樣,只能時A端口和B端口不同。

正常集羣的例子:

server.1=192.168.56.11:2181:2182
server.2=192.168.56.12:2181:2182
server.3=192.168.56.13:2181:2182

僞集羣的例子:

server.1=192.168.56.11:2181:3181
server.2=192.168.56.11:2182:3182
server.3=192.168.56.11:2183:3183

單實例安裝

安裝zookeeper服務

cd /usr/local/src/
tar -zxf zookeeper-3.4.7.tar.gz 
mv zookeeper-3.4.7 /usr/local/
ln -s /usr/local/zookeeper-3.4.7/ /usr/local/zookeeper
cd /usr/local/zookeeper
cd conf/
cp zoo_sample.cfg zoo.cfg

編輯配置文件

vim zoo.cfg 
tickTime=2000
dataDir=/data/zk
clientPort=2181

啓動zookeeper服務

/usr/local/zookeeper/bin/zkServer.sh start

檢查服務是否正常啓動

bin/zkCli.sh -server 127.0.0.1:2181

僞集羣配置

cd /usr/local/src
wget http://mirrors.cnnic.cn/apache/zookeeper/stable/zookeeper-3.4.6.tar.gz
tar zxf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 /usr/local/
ln -s /usr/local/zookeeper-3.4.6/ /usr/local/zookeeper
cd /usr/local/zookeeper/conf/
mv zoo_sample.cfg zoo.cfg
vim zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zk1
clientPort=2181
server.1=192.168.56.11:3181:4181
server.2=192.168.56.11:3182:4182
server.3=192.168.56.11:3183:4183

建立三個目錄用來存放zookeeper數據

mkdir /data/{zk1,zk2,zk3} -p
echo "1" >/data/zk1/myid
echo "2" >/data/zk2/myid
echo "3" >/data/zk3/myid

生成三份zookeeper配置文件

cp zoo.cfg zk1.cfg
cp zoo.cfg zk2.cfg
cp zoo.cfg zk3.cfg

修改zk2和zk3的配置,使用對應的數據目錄和端口。

sed -i 's/zk1/zk2/g' zk2.cfg
sed -i 's/2181/2182/g' zk2.cfg
sed -i 's/zk1/zk3/g' zk3.cfg
sed -i 's/2181/2183/g' zk3.cfg

啓動Zookeeper

/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk1.cfg
/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk2.cfg
/usr/local/zookeeper/bin/zkServer.sh start /usr/local/zookeeper/conf/zk3.cfg

查看Zookeeper角色

/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk1.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk1.cfg
#Mode: follower
/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk2.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk2.cfg
#Mode: `leader`
/usr/local/zookeeper/bin/zkServer.sh status /usr/local/zookeeper/conf/zk3.cfg
#JMX enabled by default
#Using config: /usr/local/zookeeper/conf/zk3.cfg
#Mode: follower

鏈接Zookeeper

/usr/local/zookeeper/bin/zkCli.sh -server192.168.56.11:2181

經過上面的例子能夠看到,目前zk2是leader,其它兩個節點是follower。
本文因爲實驗環境侷限使用的是僞分佈式。
生產環境不建議使用。

集羣模式

集羣模式的配置和僞集羣基本一致.
因爲集羣模式下, 各server部署在不一樣的機器上, 所以各server的conf/zoo.cfg文件能夠徹底同樣.

下面是一個示例:

tickTime=2000 
initLimit=5 
syncLimit=2 
dataDir=/home/zookeeper/data 
dataLogDir=/home/zookeeper/logs 
clientPort=4180 
server.1=192.168.56.11:3181:4182
server.2=192.168.56.12:3181:4182
server.3=192.168.56.13:3181:4182

示例中部署了3臺zookeeper server, 分別部署在192.168.56.11, 192.168.56.12, 1192.168.56.13上. 須要注意的是, 各server的dataDir目錄下的myid文件中的數字必須不一樣,192.168.56.11 server的myid爲1, 192.168.56.12 server的myid爲2, 192.168.56.13server的myid爲3。

java優化

看了你的問題, 我還特地的查看了ZooKeeper的啓動腳本代碼。ZooKeeper啓動腳本沒有加任何參數,也就是使用jvm默認的。
若是想要加大ZooKeeper的JVM使用內存。能夠在更改{ZK_HOME}/bin/zkServer.sh,大約在109-110行。
nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
改成
nohup $JAVA "-Xmx1G -Xms1G -Dzookeeper.log.dir=${ZOO_LOG_DIR}"...

jmap -heap 查看設置是否成功

zookeeper 運維

zookeeper高級配置參數

系統屬性方式配置:即在Java中,能夠經過在啓動的命令行參數中添加-D參數來達到配置系統屬性的目的,例如-Djava.library.path=/home/admin/jdk/lib, 就是經過系統屬性來配置java.library.path的。

  • dataLogDir: 該參數有默認值:dataDir,能夠不配置,不支持系統屬性方式配置。參數dataLogDir用於配置Zookeeper服務器存儲事務日誌文件的目錄。默認狀況下,Zookeeper會將事務日誌文件和快照數據存儲在同一個目錄中,使用者應儘可能將這二者的目錄區分開來。另外,若是條件容許,能夠將事務日誌的存儲配置在一個單獨的磁盤上。事務日誌記錄對於磁盤的性能要求很是高,爲了保證數據的一致性,Zookeeper在返回客戶端事務請求響應以前,必須將本次請求對應的事務日誌寫入到磁盤中。所以事務日誌寫入的性能直接決定了Zookeeper在處理事務請求時的吞吐。針對同一塊磁盤的其餘併發讀寫操做(例如Zookeeper運行時日誌輸出和操做系統自身的讀寫等),尤爲是數據快照操做,會極大的影響事務日誌的寫性能。所以儘可能給事務日誌的輸出配置一個單獨的磁盤或是掛載點,將極大地提高Zookeeper的總體性能
  • initLimit: 該參數有默認值:10,即表示是參數tickTime值的10倍,必須配置,且須要配置一個正整數,不支持系統屬性方式配置。該參數用於配置Leader服務器等待Follower啓動,並完成數據同步的時間。Follower服務器在啓動過程當中,會與Leader創建鏈接並完成對數據的同步,從而肯定本身對外提供服務的起始狀態。一般狀況下,運維人員不用太在乎這個參數的配置,使用期默認值便可。但若是隨着Zookeeper集羣管理的數據量增大,Follower服務器在啓動的時候,從Leader上進行同步數據的時間也會相應變長,因而沒法在較短的時間完成數據同步。所以,在這種狀況下,有必要適當調大這個參數。
  • syncLimit: 該參數有默認值:5,即表示是參數tickTime值的5倍,必須配置,且須要配置一個正整數,不支持系統屬性當時配置。該參數用於配置Leader服務器和Follower之間進行心跳檢測的最大延時事件。在Zookeeper集羣運行過程當中,Leader服務器會與全部的Follower進行心跳檢測來肯定該服務器是否存活。若是Leader服務器在syncLimit時間內沒法獲取到Follower的心跳檢測響應,那麼Leader就會認爲該Follower已經脫離了和本身的同步。一般狀況下,運維人員使用該參數的默認值便可,但若是部署Zookeeper集羣的網絡環境質量較低(例如網絡延時較大或丟包嚴重),那麼能夠適當調大這個參數。
  • snapCount: 該參數有默認值:100000,能夠不配置,僅支持系統屬性方式配置:zookeeper.snapCount。參數snapCount用於配置相鄰兩次數據快照之間的事務操做次數,即Zookeeper會在snapCount次事務操做以後進行一次數據快照。
  • preAllocSize: 該參數有默認值:65536,單位是KB,即64MB,能夠不配置,僅支持系統屬性方式配置:zookeeper.preAllocSize。參數preAlloSize用於配置Zookeeper事務日誌文件預分配的磁盤空間大小。一般狀況下,咱們使用Zookeeper的默認配置65536KB便可,可是若是咱們將參數snapCount設置得比默認值更小或更大,那麼preAllocSize參數也要隨之作出變動。舉例來講:若是咱們將snapCount的值設置爲500,同時預估每次事務操做的數據量大小至多1KB,那麼參數preAllocSize設置爲500就足夠了。
  • maxClientCnxns: 該參數有默認值:60,能夠不配置,不支持系統屬性方式配置。從Socket層面限制單個客戶端與單臺服務器之間的併發鏈接數,即以IP地址粒度來進行鏈接數的限制。若是將該參數設置爲0,則表示對鏈接數不作任何限制。須要注意該鏈接數限制選項的適用範圍,其僅僅是對單臺客戶端機器與單臺Zookeeper服務器之間的鏈接數限制,並不能控制全部客戶端的鏈接數總和。另外,在3.4.0版本之前該參數的默認值都是10,從3.4.0版本開始變成了60,所以運維人員尤爲須要注意這個變化,以防Zookeeper版本變化帶來服務器鏈接數限制變化的隱患。
  • clientPortAddress: 該參數沒有默認值:能夠不配置,不支持系統屬性方式配置。針對那些多網卡的機器,該參數容許爲每一個IP地址制定不一樣的監聽端口。
  • forceSync: 該參數有默認值:yes,能夠不配置,可選配置項爲yes和no,僅支持系統屬性方式配置:zookeeper.forceSync。該參數用於配置Zookeeper服務器是否在事務提交的時候,將日誌寫入操做強制刷入磁盤(即調用java.nio.channels.FileChannel.force接口),默認狀況下是yes,即每次事務日誌寫入操做都會實時刷入磁盤。若是將其設置爲no。則能必定程度的提升Zookeeper的寫性能,但同事也會存在相似於機器斷電這樣的安全風險。
  • globalOutstandingLimit: 該參數有默認值:1000,能夠不配置,僅支持系統屬性方式配置:zookeeper.globalOutstandingLimit。參數globalOutstandingLimit用於配置Zookeeper服務器最大請求堆積數量。在Zookeeper服務器運行的過程當中,客戶端會源源不斷的將請求發送到服務端,爲了防止服務端資源(包括CPU,內存和網絡等)耗盡,服務端必須限制同時處理的請求數,即最大請求堆積數量。
  • leaderServes: 該參數有默認值:yes,能夠不配置,可選配置項爲yes和no,僅支持系統屬性方式配置:zookeeper.leaderServes。該參數用於配置Leader服務器是否可以接受客戶端的鏈接,便是否容許Leader向客戶端提供服務,默認狀況下,Leader服務器可以接受並處理客戶端的全部讀寫請求。在Zookeeper的架構設計中,Leader服務器主要用來進行對事務更新請求的協調以及集羣自己的運行時協調,所以,能夠設置讓Leader服務器不接受客戶端的鏈接,以使其專一於進行分佈式協調。
  • SkipAcl: 該參數有默認值:no,能夠不配置,可選配置項爲yes和no,僅支持系統屬性方式配置:zookeeper.skipACL。該參數用於配置Zookeeper服務器是否跳過ACL權限檢查,默認狀況下是no,即會對每個客戶端請求進行權限檢查。若是將其設置爲yes,則能必定程度的提升Zookeeper的讀寫性能,但同時也會向全部客戶端開放Zookeeper的數據,包括那些以前設置過ACL權限的數據節點,也將再也不接收權限控制。
  • xncTimeout: 該參數有默認值:5000,單位是毫秒,能夠不配置,僅支持系統屬性方式配置:zookeeper.cnxTimeout。該參數用於配置在Leader選舉過程當中,各服務器之間進行TCP鏈接建立的超時時間。
  • electionAlg: 在以前的版本中,可使用該參數來配置選擇Zookeeper進行Leader選舉時所使用的算法,但從3.4.0版本開始,Zookeeper廢棄了其餘選舉算法,只留下了FastLeaderElection算法,所以該參數目前看來沒有用了。
  • jute.maxbuffer: 該參數有默認值:1048575,單位是字節,能夠不配置,僅支持系統屬性方式配置:jute.maxbuffer。該參數用於配置單個數據節點(ZNode)上能夠存儲的最大數據量大小。一般狀況下,運維人員不須要改動該參數,同時考慮到Zookeeper上不適宜存儲太多的數據,每每還須要將該參數設置得更小。須要注意的是,在變動該參數的時候,須要在Zookeeper集羣的全部機器以及全部的客戶端上均設置才能生效。
  • minSessionTimeout/maxSessionTimeout: 這兩個參數有默認值,分別是參數tickTime值的2倍和20倍,即默認的會話超時時間在2tickTime~20tickTime範圍內,單位毫秒,能夠不配置,不支持系統屬性方式配置。這兩個參數用於服務端對客戶端會話的超時時間進行限制,若是客戶端設置的超時事件再也不該範圍內,那麼會被服務端強制設置爲最大或最小超時時間
  • autopurge.snapRetainCount: 該參數有默認值:3,能夠不配置,不支持系統屬性方式配置。從3.4.0版本開始,Zookeeper提供了對歷史事務日誌和快照數據自動清理的支持。參數autopurge.snapRetainCount用於配置Zookeeper在自動清理的時候須要保留的快照數據文件數量和對應的事務日誌萬能鍵。須要注意的是,並非磁盤上的全部事務日誌和快照數據文件均可以被清理掉–那樣的話將沒法恢復數據。所以參數autopurge.snapRetainCount的最小值是3,若是配置的autopurge.snapRetainCount值小於3的話,那麼會被自動調整到3,即至少須要保留3個快照數據文件和對應的事務日誌文件
  • autopurge.purgeInteval: 該參數有默認值:0,單位是小時,能夠不配置,不支持系統屬性方式配置。參數autopurge.purgeInterval和參數autopurge.snapRetainCount配套使用,用於配置Zookeeper進行歷史文件自動清理的頻率。若是配置該值爲0或者負數,那麼就代表不須要開啓定時清理功能。Zookeeper默認不開啓這項功能。
  • fsync.warningthresholdms: 該參數有默認值:1000,單位是毫秒,能夠不配置,僅支持系統屬性方式配置:fsync.warningthresholdms。參數fsync.warningthresholdms用於配置Zookeeper進行事務日誌fsync操做時消耗時間的報警閾值。一旦進行一個fsync操做消耗的事件大於參數fsync.warningthresholdms指定的值,那麼就在日誌中打印出報警日誌。

zookeeper經常使用四字命令

  • echo conf|nc 192.168.56.12 2181: 輸出相關服務配置的詳細信息。
  • echo cons|nc 192.168.56.12 2181: 列出全部鏈接到服務器的客戶端會話的詳細信息。客戶端IP,會話ID和最後一次與服務器交互的操做類型等。
  • echo crst|nc 192.168.56.12 2181: 功能性命令,用於重置全部的客戶端鏈接統計信息。
  • echo dump|nc 192.168.56.12 2181: 用於輸出當前集羣的全部會話信息,包括未經處理的會話和臨時節點。
  • echo envi|nc 192.168.56.12 2181: 輸出關於服務環境的詳細信息(區別於 conf 命令)包括:os.version,java.version,user.home等。
  • echo ruok|nc 192.168.56.12 2181: 測試是否啓動了該Server,若回覆imok表示已經啓動。
  • echo stat|nc 192.168.56.12 2181: 來查看哪一個節點被選擇做爲follower或者leader。
  • echo srvr|nc 192.168.56.12 2181: 和stat命令的功能一致,惟一的區別是srvr不會將客戶端的鏈接狀況輸出。
  • echo reqs|nc 192.168.56.12 2181: 列出未經處理的請求。
  • echo srst|nc 192.168.56.12 2181: 功能性,用於重置全部服務器的統計信息。
  • echo wchs|nc 192.168.56.12 2181: 列出服務器 watch 的詳細信息。
  • echo wchc|nc 192.168.56.12 2181: 經過 session 列出服務器 watch 的詳細信息,它的輸出是一個與 watch 相關的會話的列表。
  • echo wchp|nc 192.168.56.12 2181: 經過路徑列出服務器 watch 的詳細信息。它輸出一個與 session 相關的路徑。
  • echo mntr|nc 192.168.56.12 2181: 用於輸出比stat命令更爲詳細的服務器統計信息,包括請求處理的延遲狀況,服務器內存數據庫大小和集羣同步狀況,每一行都是一個kv結構。能夠用於監控。
  • echo kill|nc 192.168.56.12 2181: 關掉server

zookeeper 使用JMX監控

`vim bin/zkServer.sh`

#修改前
#ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMa
in"

#修改後
ZOOMAIN="-Dcom.sun.management.jmxremote  -Dcom.sun.management.jmxremote.local.only=false  
 -Djava.rmi.server.hostname=192.168.56.22  
 -Dcom.sun.management.jmxremote.port=9991  
 -Dcom.sun.management.jmxremote.ssl=false
 -Dcom.sun.management.jmxremote.authenticate=false  
 -Dzookeeper.jmx.log4j.disable=true  
 org.apache.zookeeper.server.quorum.QuorumPeerMain"

更改完之後重啓zookeeper服務器,使用JMX客戶端鏈接服務器:

Mbean標籤頁,能夠看到org.apache.Zookeeper節點,能夠看到服務器的基本信息,當前使用的選舉算法(ElectionType),單個客戶的最大鏈接數(MaxClientCnxnsPerHost),會話的超時時間和啓動時間等。

阿里使用taokafka進行監控。

集羣數量的補充

zookeeper任意集羣數量均可以成功。官方之因此說奇數是對zookeeper的過半數存活便可用有誤解。
好比:咱們想要搭建容許F臺服務down掉的集羣,那麼就要部署一個有2xF+1臺服務器構成的zookeeper集羣。所以一個3臺機器構成的zookeeper集羣,可以在掛掉1臺機器後依然正常工做,而對於一個由5臺服務器構成的zookeeper集羣,可以對2臺機器掛掉的狀況下進行容災,可是若是是一個由6臺機器構成的zookeeper集羣,一樣只能掛掉2臺機器,若是掛掉3臺,剩下的機器就沒法實現過半了。
可是6臺跟5臺容災能力沒有任何顯著的優點,全部官方建議奇數。

擴容和縮容

因爲zookeeper對於水平擴容的支持不是特別好,全部,水平擴容只能經過總體集羣重啓,或逐臺進行重啓。

總體集羣重啓前創建的客戶端會話,並不會由於重啓而失效。也就是說總體重啓期間花費的時間將不計入會話超時時間的計算中。

數據和日誌管理

zookeeper會不斷寫入數據快照和事務日誌,zookeeper自己不會本身刪除過時的數據,須要本身手動清除。

方法一:寫shell腳本

datalogdir=//data/app/zookeeper/zk_log/version-2
datadir=/data/app/zookeeper/zk_data/version-2
logdir=/var/log/zookeeper
count=60
count=$[$count+1]
ls -t $datalogdir/log.* |tail -n _$count |xargs rm -f 
ls -t $datadir/snapshot.* |tail -n _$count |xargs rm -f 
ls -t $logdir/zookeeper.log.* |tail -n _$count |xargs rm -f

方法二:使用官方提供的日誌清理jar包
PurgeTxnLog 它的實現了一種簡單的歷史文件清理策略,能夠在這裏看一下他的使用方法:http://zookeeper.apache.org/doc/r3.4.3/api/index.html,能夠指定要清理的目錄和須要保留的文件數目

java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf org.apache.zookeeper.server.PurgeTxnLog <dataDir><snapDir> -n <count>

方法三:使用自帶的cleanup.sh腳本

zkCleanup.sh -n 15

方法四:配置文件中增長自動刪除的參數。
3.4 之後增長了自動清空歷史快照數據和事務日誌文件的機制,參考:autopurge.snapRetainCount 和 autopurge.purgeInterval 。

  • autopurge.purgeInterval 這個參數指定了清理頻率,單位是小時,須要填寫一個1或更大的整數,默認是0,表示不開啓本身清理功能。
  • autopurge.snapRetainCount 這個參數和上面的參數搭配使用,這個參數指定了須要保留的文件數目。默認是保留3個。

磁盤選擇

使用單獨的磁盤做爲事務日誌的輸出目錄。一方面事務日誌的寫性能對zookeeper處理客戶端請求,尤爲是更新操做的出來性能影響很大。另外一方面,zookeeper事務日誌輸出是一個順序寫文件的過程,所以自己性能是很是高的,全部儘可能保證不要和應用程序共享一塊磁盤,以免對磁盤的競爭。通常zookeeper事務日誌和快照數據分別配置在兩塊單獨掛載的硬盤上。
儘可能避免內存與磁盤空間的交換。若是但願zookeeper可以提供徹底實時的服務,那麼就不能出現此類內存與磁盤空間交換的現象。所以在分配JVM堆大小的時候必定要很是當心。

zookeeper client 命令

建立

create 能夠建立一個zookeeper節點

create [-s] [-e] path data acl
  • -s 或 -e 分別指定節點特性:順序和臨時節點。默認狀況下不添加-s或-e參數的,建立的是持久節點。
create /zk-book 123

讀取

讀取能夠用ls或set命令。
ls 能夠列出zookeeper指定節點下的全部子節點。固然,這個命令只能看到指定節點下第一級的全部子節點。

ls path [watch]
  • path表示的是指定節點數據的節點路徑。
ls /

第一次不是的zookeeper集羣,默認在根節點下面有一個叫作zookeeper的保留節點。

get命令能夠獲取zookeeper指定節點的數據內容和屬性信息。

get path [watch]
get /zk-book

第一行是節點/zk-book的數據內容,其餘機會則是建立改節點的事務id(cZxid),最後一次更新改節點的事務ID(mZxid)和最後一次更新改節點的時間(mtime)等屬性信息。

更新

使用set命令能夠更新指定節點的數據內容。

set path data [version]

data 就是要更新的新內容。set命令後面還有一個version參數,在zookeeper中,節點的數據是有版本概念的,這個參數用於指定本次更新操做是基於ZNode的哪個數據版本進行的。

set /zk-book 456
  • 更新完畢後,dataVersion的值由原來的0變成1,這是由於更新操做致使該節點的數據版本也發生了變動。

刪除

使用delete 命令,能夠刪除zookeeper上的指定節點

delete path [version]

此命令中的version參數跟set命令中的version參數的做用是一致的。

delete /zk-book

要想刪除某一個指定節點,改節點必須沒有子節點存在,能夠經過執行以下命令來進行驗證

create /zk-book 123
create /zk-book/child 12345
delete /zk-book

參考文檔

分佈式服務框架 Zookeeper -- 管理分佈式環境中的數據
zookeeper深刻淺出
從PAXOS到ZOOKEEPER分佈式一致性原理與實踐
Zookeeper原理與優化
zookeeper 可視化管理工具

相關文章
相關標籤/搜索