【金三銀四】Zookeeper常用場景使用介紹

Zookeeper主要是基於文件系統和監聽通知機制,可以用於統一命名服務、分佈式配置管理、集羣管理、分佈式鎖、分佈式隊列、負載均衡等功能。

文件系統結構

Zookeeper維護一個類似文件系統的數據結構:
在這裏插入圖片描述
每一個子目錄,如NameService稱之爲一個znode目錄節點,和文件系統一樣,我們可以對znode節點進行添加、刪除操作,在znode的子節點下添加刪除操作,唯一的不同是znode是可以保存數據的,數據還包含當前版本、數據版本、建立時間和修改時間等

數據類型

Zookeeper支持四種類型的節點數據:
持久化目錄節點(persistent):客戶端與zookeeper斷開連接後,該節點依然存在
持久化順序編號目錄節點(persistent_sequential):與持久化目錄節點一樣,不過Zookeeper給該節點進行順序編號
臨時目錄節點(ephemeral):客戶端與zookeeper斷開連接後,該節點被刪除
臨時順序編號目錄節點(ephemeral_sequential):與臨時目錄節點一樣,不過Zookeeper給該節點進行順序編號

監聽通知機制

客戶端監聽它所關心的目錄節點,當目錄節點發生變化(數據改變、刪除、子目錄節點發生變化)的時候,zookeeper會通知客戶端,在Zookeeper中,默認有二種角色,Follower、Leader,一個Zookeeper集羣在同一時刻只會有一個Leader,其餘都是Follower,我們還可以添加Observer角色,如果想使用Observer模式,在任何想變成Observer的節點的配置文件中加入:peerType=Observer。Leader服務器可以爲客戶端提供讀和寫操作,而Follower和Observer都只能提供讀服務,唯一的區別是Observer不參與Leader選舉過程,也不參與寫操作(過半寫成功)策略,因此Observer可以在不影響寫性能的情況下提升集羣的讀性能。

應用場景

Zookeeper所有的功能都是基於文件系統和監聽通知機制來完成的,下面來講解一下各個功能的實現原理:

分佈式配置管理

分佈式配置原理圖
在大型系統中,我們部署的項目可能超過上百臺機器,當我們在修改配置的時候,不可能每一臺機器都去修改一下,這樣維護起來太複雜了,所以我們可以將配置文件通過Zookeeper來管理,在Zookeeper中創建一個Configuration的目錄節點,所有應用程序都監聽這個目錄節點,一旦配置文件的信息發生變化,Zookeeper會通知每個應用,然後每個應用從Zookeeper中獲取最新的配置信息。

Zookeeper集羣環境Zookeeper集羣環境圖

如上圖,我們在三臺服務器上部署了Zookeeper的集羣環境,在三臺機器的Zookeeper啓動完成後,會選舉一臺機器爲Leader,負責客戶端的的讀和寫請求,其他兩條機器爲Follower,只能負責讀請求
場景模擬:當我們通過zkclient在192.168.1.1的機器上創建了一個/hello的數據節點,會發現這臺Follower也能寫成功,並且在192.168.1.2或者192.168.1.3的機器上都能夠獲取到,那麼是不是就與上面的Follower只能負責讀理論衝突了?其實並沒有衝突,而是Follower在接受到寫請求後,它會將寫請求轉給Leader節點,讓Leader節點去處理寫請求,Leader寫成功後會通知同步到各個Follower節點,這樣做的目的是保證數據的唯一性,過程如下:
集羣場景模擬圖
1、 Client向Follower發起一個寫請求
2、 Follower把寫請求轉發給Leader
3、 Leader接收到請求以後開始發起投票並通知Follower進行投票
4、 Follower把投票結果發送給Leader
5、 Leader將結果彙總,發現如果超過一半的節點支持寫入,那麼投票成功,則開始寫入同時把寫入操作通知給Follower,然後commit
6、 Follower把請求結果返回給Client

集羣選舉原理

集羣選舉原理圖
還是拿上面的寫請求作爲分析案例,當我們的Follower向Leader發送一個寫請求後,會在Leader節點生成一個全局唯一的嚴格保證順序遞增的事務ID(ZXID),因爲讀不會有事務的概念,寫纔有事務的概念,生成後Leader節點會向所有的Follower節點服務器發送請求,並且所有的Follower服務器會發送一個收到事務通知的確認消息到Leader服務器,只要Leader服務器收到超過一半的Follower服務器發過來的確認消息,Leader服務器就可以開始做Commit操作,同時也通知其他Follower服務器做Commit操作,這樣在一臺Follower服務器上寫數據後,其他服務器都能夠同步更新,這裏面涉及到兩階段提交,這樣做的目的是保證了數據的一致性,性能也比較高。
如果其中Leader節點因爲某種原因而導致服務器掛了,那麼如何保證高可用呢,Zookeeper會通過集羣選舉一個新的節點作爲Leader節點,實現如下:當Leader節點不可用的時候,所有的Follower節點會向集羣中其他的存活的Follower節點發送投票消息,該消息格式爲(myid,zxid),每臺服務器當然是優先投自己,其中myid爲集羣搭建的時候我們自己配置的,zxid爲該服務器最新的zxid,每臺機器的zxid由於受到Leader消息的前後可能會不一樣,當每臺機器接受到來自不同Follower發送的消息後,根據最大的zxid進行pk,誰的最大,誰的票數最多,然後其他的票數作廢,因爲最大的zxid的服務器肯定能保證數據是最新最全的,當每臺服務器選舉出來結果後會做更新操作,同時會向其他服務器發通知,其他服務器收到投票通知後,當其中一臺服務器得到的票數大於總服務器數的一半,那麼該服務器就成功選舉成爲Leader,所以我們在搭建集羣環境的時候,最好搭建的集羣數量爲奇數,集羣Leader選舉和集羣消息廣播(兩階段提交)的組合就是zab原子廣播協議。Zookeeper沒有用到paxos算法來保證數據一致性,zab協議其實是paxos算法的一個變種。

分佈式鎖

分佈式鎖主要用於在分佈式環境中保護跨進程、跨主機、跨網絡的共享資源實現互斥訪問,以達到保證數據的一致性。Zookeeper實現分佈式鎖是通過持久節點和臨時順序節點來完成的,實現思路如下:
在這裏插入圖片描述
1、 在指定目錄下創建一個持久節點,例如lock節點(zookeeper裏面的znode節點會自動同步,而且是強一致性的,創建一個節點後只有zookeeper集羣同步完成後纔算成功)
2、 每當進程需要訪問共享資源的時候,會在lock下面建立響應的順序臨時子節點,例如tmp_node1、tmp_node2、tmp_node3
3、 建立臨時順序子節點後,判斷建立的子節點的順序號(臨時子節點創建會自動生成一個順序號)是否爲最小節點,如果是最小節點,就可以獲得鎖對資源進行訪問
4、 如果該節點不是最小節點,那麼就獲得該節點的上一個順序節點,並給該節點註冊監聽事件監聽
5、 當客戶端關閉與zookeeper連接之後,會刪除當前的臨時子節點,釋放當前的鎖,下面的臨時節點會得到通知,並判斷自己的節點是否爲當前最小的,如果是則獲取共享鎖,如果不是則繼續第4步對比自己小的節點註冊監聽事件
流程如下:
在這裏插入圖片描述
創作不容易,歡迎大家關注2B哥微信公衆號:(Java2B)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章