Apache Zookeeper 由 Apache Hadoop 的 Zookeeper 子項目發展而來,現已經成爲 Apache 的頂級項目,它是一個開放源碼的分佈式應用程序協調服務,是Google Chubby的一個開源實現。它是一個爲分佈式應用提供一致性服務的組件,提供的功能包括:配置管理,名字服務,提供分佈式同步、隊列管理、集羣管理等。
使用場景(即上述的功能):典型應用場景篇一,典型應用場景篇二
原理:Zookeeper 從設計模式角度來看,是一個基於觀察者模式設計的分佈式服務管理框架,它負責存儲和管理大家都關心的數據,然後接受觀察者的註冊,一旦這些數據的狀態發生變化,Zookeeper 就將負責通知已經在 Zookeeper 上註冊的那些觀察者做出相應的反應,從而實現集羣中類似 Master/Slave 管理模式。
1、安裝
Zookeeper有兩種運行模式:
1.1、獨立模式(standalone mode)
(具體參考:http://blog.csdn.net/csfreebird/article/details/44006453)
只運行在一臺服務器上,適合測試環境。
1.2、複製模式(replicated mode)
運行於一個集羣上,適合生產環境,這個計算機集羣被稱爲一個“集合體”(ensemble)。
Zookeeper通過複製來實現高可用性,只要集合體中半數以上的機器處於可用狀態,它就能夠保證服務繼續。這跟Zookeeper的複製策略有關:Zookeeper確保對znode樹的每一個修改都會被複制到集合體中超過半數的機器上。
由於ZooKeeper集羣,會有一個Leader負責管理和協調其他集羣服務器,因此服務器的數量通常都是奇數,例如3,5,7...等,這樣2n+1的數量的服務器就可以允許最多n臺服務器的失效。
(安裝可參考:http://blog.csdn.net/csfreebird/article/details/44007295)
這裏以zookeeper-3.4.8爲例:
1.2.1、下載解壓
解壓後目錄結構爲:
. ├── bin ├── build.xml ├── CHANGES.txt ├── conf ├── contrib ├── dist-maven ├── docs ├── ivysettings.xml ├── ivy.xml ├── lib ├── LICENSE.txt ├── NOTICE.txt ├── README_packaging.txt ├── README.txt ├── recipes ├── src ├── zookeeper-3.4.8.jar ├── zookeeper-3.4.8.jar.asc ├── zookeeper-3.4.8.jar.md5 └── zookeeper-3.4.8.jar.sha1
1.2.2、配置文件
進入conf目錄, cp zoo_sample.cfg zoo.cfg ,修改配置文件zoo.cfg爲如下:
各配置項的含義:
每個節點的配置文件都一樣。
更多可參考Zookeeper的配置
1.2.3、添加myid文件
除了修改 zoo.cfg 配置文件,集羣模式下還要配置一個文件 myid,這個文件在 上述dataDir 指定的目錄下,這個文件裏面就只有一個數據就是 A 的值,Zookeeper 啓動時會讀取這個文件,拿到裏面的數據與 zoo.cfg 裏面的配置信息比較從而判斷到底是那個 server。
1.2.4、啓動/結束
bin/zkServer.sh start|start-foreground|stop|restart|status|upgrade|print-cmd ,啓動後默認在bin下產生日誌文件zookeeper.out
1. 啓動ZK服務: bin/zkServer.sh start 2. 查看ZK服務狀態: bin/zkServer.sh status 3. 停止ZK服務: bin/zkServer.sh stop 4. 重啓ZK服務: bin/zkServer.sh restart
(啓動後在zoo.cfg所指定的dataDir下有version-2文件夾(下有log.1文件)和zookeeper_server.pid文件)
啓動後可以藉助下面的命令行客戶端看是否能連上以確定是否成功啓動,也可使用四字命令(如 echo stat|netcat localhost 2181 )快速確定節點狀態
2、使用
2.1、Shell客戶端
2.1.1 zk命令
命令行客戶端連接ZooKeeper: ./bin/zkCli.sh -server localhost:2181 ,連接成功後,會輸出 ZooKeeper 的相關環境以及配置信息。並能進行一些操作:
1. 顯示根目錄下、文件: ls / 使用 ls 命令來查看當前 ZooKeeper 中所包含的內容 2. 顯示根目錄下、文件: ls2 / 查看當前節點數據並能看到更新次數等數據 3. 創建文件並設置初始內容:create /zk "test" 創建一個新的 znode節點“ zk ”以及與它關聯的字符串 4. 獲取文件內容: get /zk 確認 znode 是否包含我們所創建的字符串 5. 修改文件內容: set /zk "zkbak" 對 zk 所關聯的字符串進行設置 6. 刪除文件: delete /zk 將剛纔創建的 znode 刪除 7. 刪除目錄(即使非空):rmr 目錄 如可用於刪除Kafka的某個Consumer Group 8. 退出客戶端: quit 9. 幫助命令: help
客戶端連接後,用get / 命令可以發現此時只有zookeeper一項;如果此Zookeeper用於對Kafka或JStorm等提供服務,則還會有相應的其他目錄。
2.1.2 四字命令
此外,也可通過四字命令更方便地獲取服務端信息, 四字命令的用法爲 echo 四字命令|netcat localhost 2181 ,常用的四字命令如下:
- conf:輸出Zookeeper服務器配置的詳細信息
- cons:輸出所有連接到服務器的客戶端的完全的連接/會話的詳細信息。包括“接收/發送”的包數量、會話ID、操作延遲、最後的操作執行等
- dump:輸出未經處理的會話和臨時節點
- envi:輸出關於服務器運行環境的詳細信息
- reqs:輸出未經處理的請求
- ruok:測試服務是否處於正確狀態。若是則會返回“imok”,否則不做任何反應
- stat:輸出關於性能和連接的客戶端的列表。(通過此命令也可查看節點是leader還是follower)
- wchs:輸出服務器watch的詳細信息
- wchc:通過session列出服務器watch的詳細信息,它的輸出是一個與watch相關的會話的列表
- wchp:通過路徑列出服務器watch的詳細信息,它輸出一個與session相關的路徑
- mntr:輸出一些Zookeeper運行時信息,通過對這些返回結果的解析可以達到監控效果
2.2、Java客戶端
使用Java進行Zookeeper的CRUD操作,示例如下:
相關Maven依賴:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.2</version>
</dependency>
3、Zookeeper dashboard
GitHub Zookeeper UI Dashboard
4、進階
4.1 數據及日誌維護
Zookeeper的數據文件存放在配置中指定的dataDir中,每個數據文件名都以snapshot開頭,每個數據文件爲zookeeper某個時刻數據全量快照。在zookeeper中,對數據的更新操作,包括創建節點、更新節點內容、刪除節點都會記錄事務日誌;客戶端對ZK的更新操作都是永久的,不可回退的。爲做到這點,ZK會將每次更新操作以事務日誌的形式寫入磁盤,寫入成功後纔會給予客戶端響應。zookeeper在完成若干次事務日誌(snapCount)後會生成一次快照,把當前zk中的所有節點的狀態以文件的形式dump到硬盤中,生成一個snapshot文件。這裏的事務次數是可以配置,默認是100000個。
Zookeeper的日誌包括兩個部分,一部分是系統日誌,另一部分是事務日誌。
系統日誌使用log4j進行管理,conf目錄中有一個log4j配置文件,該配置文件默認沒有打開滾動輸出,需要用戶自己配置,具體請參看log4j介紹。
事務日誌默認存放在dataDir中,當然可以使用dataLogDir指定存放的位置。正常運行過程中,針對所有更新操作,在返回客戶端“更新成功”的響應前,ZK會確保已經將本次更新操作的事務日誌寫到磁盤上,只有這樣,整個更新操作纔會生效。每觸發一次數據快照,就會生成一個新的事務日誌。
默認情況下,zk不會自動清理數據文件和日誌文件,因此需要管理員自己清理。我們可以使用ZK的工具類PurgeTxnLog進行清理,當然,我們也可以寫腳本自己維護,同時可以使用工具慢慢清理,避免佔用大量IO。清理腳本如下:
務必注意:
如果長時間不清理,切忌同一時間使用rm命令同時刪除大量文件,這樣會造成IO利用率瞬間飆升,zookeeper的連接會出現斷連或session超時,影響現網業務使用。
另外,對於每一個數據文件,它都是某一時刻的完整快照,我們可以定時將該文件備份,方便對數據進行還原或將zookeeper直接遷移到另外一個集羣。
4.2 數據清理
具體詳見:http://nileader.blog.51cto.com/1381108/932156
4.3 可視化事務日誌
具體詳見:http://nileader.blog.51cto.com/1381108/926753
Zookeeper運行久了產生的日誌和事務數據非常大,在我們的實踐中甚至由於從沒清理導致磁盤滿了,雖然Zookeeper節點沒死,但ZK UI監控上顯示出“This instance is not serviceing requests”。由於Zookeeper不能提供服務,JStorm節點就死了,Kafka節點也無法提供服務(沒死),清理數據後就好了。
上述參考資料裏列出了幾種方法,我們採取定時自動清理的做法(每次留10個),寫如下腳本,加入crontab定期執行:
#snapshot file dir dataDir=/usr/local/zookeeper/zookeeper-3.4.8/zk_data/version-2 #tran log dir dataLogDir=/usr/local/zookeeper/zookeeper-3.4.8/zk_data/version-2 #zk log dir #Leave 10 files count=10 count=$[$count+1] ls -t $dataLogDir/log.* | tail -n +$count | xargs rm -f ls -t $dataDir/snapshot.* | tail -n +$count | xargs rm -f
4.4 權限控制
具體參見:使用super身份對有權限的節點進行操作 和 ZooKeeper權限控制
4.5 Zookeeper應用場景及實踐
經典應用:
1)NameService
不多說,本身就是一個共享的樹形文件系統
2)配置管理
不同的process watch 自己的配置znode, 當配置變化可以收到通知
3)集羣membership管理
集羣節點下,每個server對應一個EPHEMERAL的節點,節點名就是server name/ IP,當它和zookeeper的心跳斷了,對應的節點被刪除,並且所有集羣內的節點可以收到新的child List,保證每個server都知道進羣內的其他server
4) master選舉
和3)類似,但是節點換成EPHEMERAL_SEQUENTIAL的,大家都約定以當前編號最小的server做爲master。當master掛了,每個server都會被通知到一份新的server 列表,大家都把編號最小的那個作爲master
5) 分佈式獨佔鎖
類似Java synchronized的語義 在約定的鎖節點上創建EPHEMERAL_SEQUENTIAL節點作爲等待隊列,如果編號最小的就是自己就獲得鎖,否則wait()住。獲得鎖的process通過刪除自己的節點釋放鎖,這樣每個等待的process會得到通知,在事件處理函數裏判斷自己是不是最小的編號,如果是則喚醒之前wait住的線程,這樣本進程就獲得了鎖
6)barrier屏障
意思是所有相關的process都到達齊了再往下執行。實現方法,也是在barrier節點創建EPHEMERAL_SEQUENTIAL的節點,每個process都會得到變化後的children list,當大小爲barrier要求數的時候,各個process繼續執行。 zookeeper作爲分佈式process協調的中介,本身是一個單點failure點,所以它本身也做爲一個集羣,通常部署2n + 1臺, 客戶端連接不同的zookeeper server,但是得到視圖是一樣的,這點是zookeeper內部保證的
Zookeeper客戶端主要有原生客戶端、zclient、Apache Curator等。
以下代碼使用Zookeeper原生的客戶端(Zookeeper源碼裏),推薦使用更方便的客戶端 Curator
4.5.1 配置管理
4.5.2 集羣管理
4.5.3 分佈式同步鎖、隊列等
5、參考資料
1、http://blog.csdn.net/csfreebird/article/details/43984425(安裝)
2、http://www.cnblogs.com/yuyijq/p/3424473.html(Zookeeper系列)
3、http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html(使用和原理探究)
4、http://data.qq.com/article?id=2863(全。騰訊大數據之Zookeeper運營經驗分享)