Zookeeper是Hadoop分布式調度服務,用來構建分布式應用系統。構建一個分布式應用是一個很復雜的事情,主要的原因是我們需要合理有效的處理分布式集群中的部分失敗的問題。例如,集群中的節點在相互通信時,A節點向B節點發送消息。A節點如果想知道消息是否發送成功,只能由B節點告訴A節點。那么如果B節點關機或者由於其他的原因脫離集群網絡,問題就出現了。A節點不斷的向B發送消息,並且無法獲得B的響應。B也沒有辦法通知A節點已經離線或者關機。集群中其他的節點完全不知道B發生了什么情況,還在不斷的向B發送消息。這時,你的整個集群就發生了部分失敗的故障。
Zookeeper不能讓部分失敗的問題徹底消失,但是它提供了一些工具能夠讓你的分布式應用安全合理的處理部分失敗的問題。
Zookeeper基本
是什么
是一個基於觀察者模式設計的分布式服務管理框架,他負責存儲和管理大家都關心的數據,然后接受管擦者的注冊,一旦這些數據的狀態發生了變化,Zookeeper就將負責通知已經在Zookeeper上注冊的觀察者做出相應的反應。
特點是什么
集群中半數以上的機器存活,Zookeeper集群就可以正常服務。
集群數據保持一致,每一個Server保存一分相同的數據副本,Client無論連接那個Server,數據都是一致的。
Zookeeper的工作機制
Zookeeper 特點
- Zookeeper: 一個領導者(Leader) , 多個追隨者(Follower) 組成的集群;
- 集群中只要有半數以上節點存活,Zookeeper 集群就能正常服務;
- 全局數據一致,每個Server保存一份相同的數據副本,Client 無論連接到哪個 Server , 數據都是一致的。
- 更新請求順序進行,來自同一個Client 的更新請求按其發送順序依次執行;
- 數據更新原子性,一次數據更新要么成功,要么失敗。
- 實時性,在一定時間范圍內,Client能讀到最新的數據。
Zookeeper 的重要概念
- Zookeeper 本身就是一個分布式程序(半數以上的節點存活,Zookeeper 就能正常服務)
- 為了保證高可用,最好是以集群形態來部署 Zookeeper , 這樣只要集群中大部分機器是可用的(能夠容忍一定的機器故障),那么Zookeeper 本身任然是可用的。
- Zookeeper 將數據保存在內存中,這也就保證了高吞吐量和低延遲(但是內存限制了能夠存儲的容量不太大,此限制也是保持 znode 中存儲的數據量較小的進一步原因)。
- Zookeeper 是高性能的。在 “讀” 多於 “寫” 的應用程序中尤其的 高性能。因為“寫” 會導致所有的服務器間同步狀態(“讀” 多於 “寫” 是協調服務的典型場景)。
- Zookeeper 有臨時節點的概念。當創建臨時節點的客戶端會話一直保持活動,瞬時節點就一直存在。而當會話終結時,瞬時節點被刪除。持久節點是指一旦這個 ZNode 被創建,除非主動進行 ZNode 的移除操作,否則這個 ZNode 將一直保存在 Zookeeper 上。
- Zookeeper 底層其實只提供了兩個功能:① 管理(存儲、讀取)用戶程序提交的數據; ② 為用戶程序提交數據節點監聽服務
Session (會話)
Session 是指 Zookeeper 服務器與客戶端會話。在 Zookeeper 中,一個客戶端連接是指客戶端和服務器之間的 TCP 長連接。客戶端啟動的時候,首先會和服務器建立一個 TCP 連接,客戶端能夠通過 心跳 檢測和服務保持有效的會話,也能夠向 Zookeeper 服務器發送請求並接受響應,同時還能通過該鏈接接收來自服務器的 Watch 事件通知。
Session 的 sessionTimeout 值用來設置一個客戶端會話的超時時間。當用於服務器壓力太大、網絡故障或是在客戶端主動斷開連接等各種原因導致客戶端連接斷開的時,只要在 sessionTimeout 規定的時間內能夠重新連接上集群中任意一台服務器,那么之前創建的會話依然有效。
在為客戶端創建會話之前,服務端首先會為每個客戶端都分配一個 sessionID , 由於 sessionID 是 Zookeeper 會話的一個重要標識,許多與會話相關的運行機制都是基於這個 sessionID 的(也就是,這個 sessionID 全局唯一) 。
Znode
在分布式中,所謂的節點是指集群中的每一台機器,稱為機器節點。但是在 Zookeeper 中, 我們的節點有兩種,一種是 機器節點 , 另一種就是 數據模型中的數據單元,也就是我們稱為的數據節點——Znode 。
Zookeeper 將所有的數據存儲在內存中,數據模型是一個 Znode Tree 。主節點是 / ,如下所示:
在節點中,我們又有持久節點和臨時節點一說。所謂持久節點,除非你進行了ZNode的移除操作,否則 Zookeeper 將一直保留在 Zookeeper 上。臨時節點不同的是,它的生命周期和當前會話一致。一旦會話結束,這個臨時節點也就結束了。另外,Zookeeper 允許用戶為每個節點添加一個特殊屬性: SEQUENTIAL , 一旦節點被標記上這個屬性,那么在節點被創建的時候,Zookeeper 會自動在其節點后面追加上一個整型數字,這個數字是一個由父節點維護的自增數字。
版本
每個 Znode 上都會存儲數據,對應每個 ZNode , Zookeeper 會維護一個 Stat 的數據結構。 Stat 記錄了這個 ZNode 的三個數據版本,分別是 version(當前的 ZNode 版本),cversion(當前 ZNode 子節點的版本), 和 cversion(當前 ZNode 的 ACL 版本)。
Watcher
Watcher(事件監聽器), 是Zookeeper 中的一個很重要的特性。Zookeeper 允許用戶在指定節點上注冊一些 Watcher ,並且在一些特定事件觸發的時候, Zookeeper 服務端 會將事件通知到感興趣的客戶端上去,該機制是 Zookeeper 實現分布式協調服務的重要特性。
ACL
Zookeeper 通過采用 ACL (aCCESSControlLists) 策略來進行權限控制。有如下五種權限:
- create:創建子節點的權限
- READ:獲取節點數據和子節點列表的權限
- WRITE:更新節點的權限
- DELETE:刪除節點的權限
- ADMIN:設置節點ACL權限
Zookeeper 內部原理
選舉機制
1)半數機制:集群中半數以上機器存活,集群可用。所以Zookeeper適合安裝奇數台服務器。
2)Zookeeper雖然在配置文件中並沒有指定Master和Slave。但是,Zookeeper工作時,是有一個節點為Leader,其他則為Follower,Leader是通過內部的選舉機制臨時產生的。
3)以一個簡單的例子來說明整個選舉的過程。
假設有五台服務器組成的Zookeeper集群,它們的id從1-5,同時它們都是最新啟動的,也就是沒有歷史數據,在存放數據量這一點上,都是一樣的。如圖所示:
(1)服務器1啟動,此時只有它一台服務器啟動了,它發出去的報文沒有任何響應,所以它的選舉狀態一直是LOOKING狀態。
(2)服務器2啟動,它與最開始啟動的服務器1進行通信,互相交換自己的選舉結果,由於兩者都沒有歷史數據,所以id值較大的服務器2勝出,但是由於沒有達到超過半數以上的服務器都同意選舉它(這個例子中的半數以上是3),所以服務器1、2還是繼續保持LOOKING狀態。
(3)服務器3啟動,根據前面的理論分析,服務器3成為服務器1、2、3中的老大,而與上面不同的是,此時有三台服務器選舉了它,所以它成為了這次選舉的Leader。
(4)服務器4啟動,根據前面的分析,理論上服務器4應該是服務器1、2、3、4中最大的,但是由於前面已經有半數以上的服務器選舉了服務器3,所以它只能接收當小弟的命了。
(5)服務器5啟動,同4一樣當小弟。
Stat 數據結構
1)czxid-創建節點的事務zxid
每次修改ZooKeeper狀態都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。
事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小於zxid2,那么zxid1在zxid2之前發生。
2)ctime - znode被創建的毫秒數(從1970年開始)
3)mzxid - znode最后更新的事務zxid
4)mtime - znode最后修改的毫秒數(從1970年開始)
5)pZxid-znode最后更新的子節點zxid
6)cversion - znode子節點變化號,znode子節點修改次數
7)dataversion - znode數據變化號
8)aclVersion - znode訪問控制列表的變化號
9)ephemeralOwner- 如果是臨時節點,這個是znode擁有者的session id。如果不是臨時節點則是0。
10)dataLength- znode的數據長度
11)numChildren - znode子節點數量
監聽器原理
- 首先要有一個 main() 線程;
- 在 main() 線程中創建 Zookeeper 客戶端,這時就會創建兩個線程,一個負責 網絡連接通信(connet) , 一個負責監聽(listener) .
- 通過 connet 線程將注冊的監聽事件發送給 Zookeeper.
- 在 Zookeeper 的注冊監聽器列表中將注冊的監聽事件添加到列表中 .
- Zookeeper 監聽到有數據或路徑變化,就會將這個消息發送到 listener 線程 .
- listener 線程內部調用了 process() 方法 .
Zookeeper的集群搭建
這是我的zookeeper的集群環境配置:
# The number of milliseconds of each tick
tickTime=30000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/opt/module/zookeeper-3.4.10/dataDir
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.101=hadoop101:2888:3888
server.102=hadoop102:2888:3888
server.103=hadoop103:2888:3888
在我們的 /opt/module/zookeeper-3.4.10/dataDir
中,我們需要添加 myid文件,且每個節點的myid內容必須保持不一致,如筆者的分別為:101,102,103.內容如下:
101
隨后,我們便分發到各個機器上去。按要求修改相應的2內容。
Zookeeper的基本命令操作
我們看下Zookeeper的客戶端操作:
1.進入客戶端
bin/zkCli.sh
2.顯示所有的操作命令
help
3.查看當前znode中包含的內容
ls /
4.查看當前znode中詳細數據信息
ls2 /
5.分別創建2個普通節點
create /sanguo "jinlian"
create /sanguo/shuguo "liubei"
6.獲得節點的值
get /sanguo
7.創建短暫節點
create -e /sanguo/wuguo "zhouyu"
# 僅在當前客戶端下可以看到的目錄,退出當前客戶端或者使用第二客戶端當前所創建的目錄軍備自動刪除
8.創建帶序號的節點
# 先創建一個普通的根節點
create /sanguo/weiguo "caocao"
# 開始創建一個帶序號的節點
create -s /sanguo/weiguo/xiaoqiao "jinlian"
create -s /sanguo/weiguo/daqiao "jinlian"
create -s /sanguo/weiguo/diaocan "jinlian"
9.修改節點數據值
set /sanguo/weiguo "simayi"
10.節點的值變化監聽
get /sanguo watch
11.節點的子節點變化監聽(路徑變化)
# 在hadoop104主機上注冊監聽/sanguo節點的子節點變化
ls /sanguo watch
# 在hadoop103主機/sanguo節點上創建子節點
create /sanguo/jin "simayi" Created /sanguo/jin
# 觀察hadoop104主機收到子節點變化的監聽
12.刪除節點
delete /sanguo/jin
13.遞歸刪除節點
rmr /sanguo/shuguo
14.查看節點狀態
stat /sanguo
Zookeeper API
這部分內容,后續有時間在寫,目前這個API用的比較少,至少我所在的公司不會有這個要求。讀者也可以在網上搜索,會有一大堆的。