一文了解Zookeeper
Zookeeper是Apache開源的一個分布式框架,它主要為分布式應(yīng)用提供協(xié)調(diào)服務(wù)。
Zookeeper主要負責存儲和管理大家都關(guān)心的數(shù)據(jù),一旦這些數(shù)據(jù)的狀態(tài)發(fā)生變化,Zookeeper就會通知那些注冊在Zookeeper上的服務(wù)。簡單來講就是zookeeper=文件系統(tǒng)+通知機制。
一 Zookeeper的數(shù)據(jù)結(jié)構(gòu)
Zookeeper的數(shù)據(jù)結(jié)構(gòu)與Unix文件系統(tǒng)很類似,整體上可以看作是一棵樹,與Unix文件系統(tǒng)不同的是Zookeeper的每個節(jié)點都可以存放數(shù)據(jù),每個節(jié)點稱作一個ZNode,默認存儲1MB的數(shù)據(jù),每個ZNode都可以通過其路徑唯一標識。
1.1 四種類型的ZNode
- 持久化目錄節(jié)點:客戶端與Zookeeper斷開連接后,該節(jié)點依舊存在。
- 持久化順序編號目錄節(jié)點:客戶端與Zookeeper斷開連接后,該節(jié)點依舊存在,只是Zookeeper給該節(jié)點名稱就行順序編號。
- 臨時目錄節(jié)點:客戶端與Zookeeper斷開連接后,該節(jié)點被刪除。
- 臨時順序編號目錄節(jié)點:客戶端與Zookeeper斷開連接后,該節(jié)點被刪除,只是Zookeeper給該節(jié)點名稱就行順序編號。
說明:創(chuàng)建ZNode時設(shè)置順序標識,ZNode名稱后會附加一個值,順序號是一個單調(diào)遞增的計數(shù)器,由父節(jié)點維護。
1.2 stat結(jié)構(gòu)體
ZNode主要包含以下信息:
- czxid-創(chuàng)建節(jié)點的事務(wù) zxid:
每次修改 ZooKeeper 狀態(tài)都會收到一個 zxid 形式的時間戳,也就是 ZooKeeper 事務(wù) ID。
事務(wù) ID 是 ZooKeeper 中所有修改總的次序。每個修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前發(fā)生。
- ctime :znode 被創(chuàng)建的毫秒數(shù)(從 1970 年開始)
- mzxid:znode 最后更新的事務(wù) zxid
- mtime:znode 最后修改的毫秒數(shù)(從 1970 年開始)
- pZxid:znode 最后更新的子節(jié)點 zxid
- cversion:znode 子節(jié)點變化號,znode 子節(jié)點修改次數(shù)
- dataversion:znode 數(shù)據(jù)變化號
- aclVersion:znode 訪問控制列表的變化號
- ephemeralOwner:如果是臨時節(jié)點,這個是 znode 擁有者的 session id。如果不是臨時節(jié)
點則是 0
- dataLength:znode 的數(shù)據(jù)長度
- numChildren:znode 子節(jié)點數(shù)量
二 Zookeeper的應(yīng)用場景
Zookeeper的主要應(yīng)用場景有統(tǒng)一命名服務(wù),統(tǒng)一配置管理,統(tǒng)一集群管理,服務(wù)器節(jié)點動態(tài)上下線等。
2.1 統(tǒng)一命名服務(wù)
在分布式環(huán)境中,經(jīng)常需要對服務(wù)進行統(tǒng)一命名,假如有一個服務(wù)部署了2兩個副本,直接調(diào)用具體的服務(wù)肯定有些不合適,因為我們并不清楚哪個服務(wù)可以更快的處理我們的請求,這時候我們可以將這三個服務(wù)進行統(tǒng)一命名,然后其內(nèi)部再去負載。這樣就可以調(diào)用最優(yōu)的那個服務(wù)了。
2.2 統(tǒng)一配置管理
分布式環(huán)境下,配置文件的同步可以由Zookeeper來實現(xiàn)。
- 將配置文件寫入Zookeeper的一個ZNode
- 各個客戶端服務(wù)監(jiān)聽這個ZNode
- 一旦ZNode發(fā)生改變,Zookeeper將通知各個客戶端服務(wù)
2.3 統(tǒng)一集群管理
Zookeeper可以實現(xiàn)實時監(jiān)控節(jié)點狀態(tài)變化,當有一個三個節(jié)點的服務(wù),假如其他一個宕機了,其他兩個節(jié)點可立即收到消息,實現(xiàn)實時監(jiān)控。將這三個節(jié)點寫入Zookeeper的一個ZNode,每個節(jié)點都去監(jiān)聽這個ZNode,當ZNode發(fā)生變化時,這些節(jié)點可實時收到變化狀態(tài)。
監(jiān)聽器的原理
- 創(chuàng)建一個Main()線程
- 在Main()線程中創(chuàng)建兩個線程,一個負責網(wǎng)絡(luò)連接通信(connect),一個負責監(jiān)聽(listener)
- 通過connect線程將注冊的監(jiān)聽事件發(fā)送給Zookeeper
- 將注冊的監(jiān)聽事件添加到Zookeeper的注冊監(jiān)聽器列表中
- Zookeeper監(jiān)聽到有數(shù)據(jù)或路徑發(fā)生變化時,把這條消息發(fā)送給Listener線程
- Listener線程內(nèi)部調(diào)用process()方法
三 Zookeeper集群
Zookeeper集群雖然沒有指定Master和Slave。但是,在Zookeeper工作時,會通過內(nèi)部選舉機制產(chǎn)生一個Leader節(jié)點,其他節(jié)點為Follower或者是Observer。
被聲明為Observer的節(jié)點,不參與選舉過程,也不參與寫操作的”過半寫成功“策略。
過半寫成功策略:Leader節(jié)點接收到寫請求后,這個Leader會將寫請求廣播給各個server,各個server會將該寫請求加入待寫隊列,并向Leader發(fā)送成功信息,當Leader收到一半以上的成功消息后,說明該寫操作可以執(zhí)行。Leader會向各個server發(fā)送提交消息,各個server收到消息后開始寫。
Follower和Observer只提供數(shù)據(jù)的讀操作,當他們接收的寫請求時,會將該請求轉(zhuǎn)發(fā)給Leader節(jié)點。
集群中只要有半數(shù)以上的節(jié)點存活,Zookeeper集群就能正常服務(wù)。因此Zookeeper集群適合安裝奇數(shù)臺機器。
3.1 選舉機制
(1)服務(wù)器 1 啟動,發(fā)起一次選舉。服務(wù)器 1 投自己一票。此時服務(wù)器 1 票數(shù)一票,不夠半數(shù)以上(3 票),選舉無法完成,服務(wù)器 1 狀態(tài)保持為 LOOKING;
(2)服務(wù)器 2 啟動,再發(fā)起一次選舉。服務(wù)器 1 和 2 分別投自己一票并交換選票信息:此時服務(wù)器 1 發(fā)現(xiàn)服務(wù)器 2 的 ID 比自己目前投票推舉的(服務(wù)器 1)大,更改選票為推舉服務(wù)器 2。此時服務(wù)器 1 票數(shù) 0 票,服務(wù)器 2 票數(shù) 2 票,沒有半數(shù)以上結(jié)果,選舉無法完成,服務(wù)器 1,2 狀態(tài)保持 LOOKING;
(3)服務(wù)器 3 啟動,發(fā)起一次選舉。此時服務(wù)器 1 和 2 都會更改選票為服務(wù)器 3。此次投票結(jié)果:服務(wù)器 1 為 0 票,服務(wù)器 2 為 0 票,服務(wù)器 3 為 3 票。此時服務(wù)器 3 的票數(shù)已經(jīng)超過半數(shù),服務(wù)器 3 當選 Leader。服務(wù)器 1,2 更改狀態(tài)為 FOLLOWING,服務(wù)器 3 更改狀態(tài)為 LEADING;
(4)服務(wù)器 4 啟動,發(fā)起一次選舉。此時服務(wù)器 1,2,3 已經(jīng)不是 LOOKING 狀態(tài),不會更改選票信息。交換選票信息結(jié)果:服務(wù)器 3 為 3 票,服務(wù)器 4 為 1 票。此時服務(wù)器 4服從多數(shù),更改選票信息為服務(wù)器 3,并更改狀態(tài)為 FOLLOWING;
(5)服務(wù)器 5 啟動,同 4 一樣當小弟。
本文轉(zhuǎn)載自微信公眾號「Java旅途」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java旅途公眾號。