zookeeper理解
生活随笔
收集整理的這篇文章主要介紹了
zookeeper理解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Zookeeper簡介
Zookeeper的數據模型
- 層次化的目錄結構,命名符合常規文件系統規范
- 每個節點在zookeeper中叫做znode,并且有一個唯一的路徑標識
- 節點znode可以包含數據和子節點,但是EPHEMERAL類型的節點不能有子節點
- Znode中的互刷可以有多個版本,比如某一個路徑下存在多個數據版本,那么查詢這個路徑下的數據就需要帶上版本號
- 客戶端應用可以在節點上設置監視器
- 節點不支持部分讀寫,而是一次性完整讀寫
Zookeeper的節點
- Znode有兩種類型,短暫的(ephemeral)和持久節點(persistent)
- Znode的類型在創建時確定并且不能修改
- 短暫的Znode的客戶端會話結束,zookeeper會將該短暫znode刪除,短暫znode不可以有子節點
- 持久Znode不依賴客戶端會話,只有當客戶端明確要刪除改Znode時候才會被刪掉
- Znode有四種形式的目錄節點:
- persistent 是永久節點
- persistent_sequential 是永久有序節點
- ephemeral 是臨時節點
- ephemeral_sequential 是臨時有序節點
Zookeeper的角色
- 領導者(leader),負責進行投票和發起決議,更新系統狀態
- 學習者(learner),包括跟隨者(follower)和觀察者(observer),follower用于接收客戶端請求并向客戶端返回結果,在選主過程中參與投票
- 觀察者(Observer),可以接受客戶端連接,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態,observer的目的是為了擴展系統,提高讀取速度。
- 客戶端(client),請求發起方:
Zookeeper的順序號
- 創建Znode時設置順序標識,znode名稱后面會附加一個值
- 順序號是一個單遞增的計數器,由父節點維護
- 在分布式系統中,順序號可以被用于所有事件進行全局排序,這樣客戶端可以通過順序號推斷事件的順序
Zookeeper的讀寫機制
- zookeeper是一個由多個server組成的集群
- 一個leader,多個follower
- 每個server保存一份數據副本
- 全局數據一致
- 分布式讀寫
- 更新請求轉發由leader實施
Zookeeper的保證
- 更新請求順序進行,來自同一個client的更新請求按其發送順序依次執行
- 數據更新原子性,依次數據更新要么成功,要么失敗
- 全局唯一數據視圖,client無論鏈接到哪個server,數據視圖都是一致的
- 實時性,在一定事件范圍內,client能督導的最新數據
Zookeeper的api接口
- String create(String path,byte[] data, List acl, CreateMode createMode):
- 創建一個給定目錄節點的path,并給他設置數據,CreateMode標識有四種形式目錄,分別是:
- PERSISTENT:持久化目錄節點,這個目錄節點存儲的數據不會丟失;
- PERSISTEN_SEQUENTIAL:順序自動編號的目錄節點,這種節點會根據當前已經存在的節點數自動加1,然后返回給客戶端已經成功創建的目錄節點名
- EPHEMERAL:臨時目錄節點,一旦創建這個節點的客戶端與服務器斷開,也就是session超時,這種節點會被自動刪除
- EPHEMERAL_SEQUENTIAL:臨時自動編號節點
- Stat exists(String path, boolean watch):
- 判斷某個path是否存在,并設置是否監控這個目錄節點,這里的watcher是在創建zookeeper實例時指定的watcher,exists方法還有一個重載方法,可以執行特定的watcher
- Stat exists(String path, Watcher watcher)
- 重載方法,這里給某個目錄節點設置特定的watcher,watcher在zookeeper是一個核心功能,watcher可以監控目錄加點的數據變化以及子目錄的變化,一旦這些狀態發生變化,服務器就會通知所有設置在這個目錄節點上的watcher,從而每個客戶端都很快知道他所關注的節點的狀態發生變化,而做出相應的反應
…
- 重載方法,這里給某個目錄節點設置特定的watcher,watcher在zookeeper是一個核心功能,watcher可以監控目錄加點的數據變化以及子目錄的變化,一旦這些狀態發生變化,服務器就會通知所有設置在這個目錄節點上的watcher,從而每個客戶端都很快知道他所關注的節點的狀態發生變化,而做出相應的反應
觀察(watcher)
- watcher在Zookeeper中是一個核心功能,watcher可以監控目錄節點的數據變化以及子目錄的變化,一旦這些狀態發生變化,服務器就會通知所有設置在這個目錄節點上的 Watcher,從而每個客戶端都很快知道它所關注的目錄節點的狀態發生變化,從而做出相應反應(一個節點可以設置多個watcher,也就是每個客戶端都可以在一個節點上設置觀察)
- 可以設置觀察的操作:exists,getChildren, getData
- 可以觸發觀察操作:create, delete,setData
寫操作與zookeeper內部事件的對應關系
寫操作與watcher的對應關系
每個znode被創建時候都會帶有一個ACL列表,用于決定誰可以對他執行何種操作
ACL訪問控制列表(Access Control List, ACL)
- 身份驗證模式有三種:
- digest:用戶名密碼
- host:通過客戶端的主機名來識別客戶端
- ip:通過客戶端的ip來識別客戶端
- new ACL(Perms.READ, new Id(“host”, “example.com”)); 這個ACL對應身份驗證模式是host,符合改模式的身份是exmple.com,權限組合是:READ
Znode的節點狀態
Zookeeper工作原理
- zookeeper的核心是原子廣播,這個機制保證了各個server之間的同步。實現這個機制的協議叫Zab協議。Zab協議有兩種模式,他們分別是恢復模式和廣播模式。當服務啟動或者在領導者崩潰后,Zab就進入恢復模式,當領導者被選舉出來,且大多數server的完成了和leader的狀態同步后,恢復模式就結束了。狀態同步保證了leader和server具有相同的系統狀態。
- 一旦leader已經和多數follower進行了狀態同步后,他就可以開始廣播消息,即進入廣播狀態。這時候,當一個server加入zookeeper服務中,他會在恢復模式下啟動,發現leader,并和leader進行狀態同步。待到同步結束,他也參與消息廣播。Zookeeper服務一直維持在broadcast狀態,直到崩潰或者leader失去了大部分followers支持。
- 廣播模式需要保證proposal被按順序處理,因此ZK采用了遞增的事務id號碼(zxid)來保證,所有的提議(proposal)都被踢出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,他都會有一個新的epoch,低32位是個遞增計數
- 當leader崩潰或者leader失去大多數follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有server都恢復到一個正確的狀態。
Leader選舉
- 每個server啟動以后都詢問其他Server他要投票給誰
- 對于其他server的詢問,server每次根據自己的狀態都回復自己推薦的leader的id和上一次處理事務的zxid(系統啟動時每個server都會推薦自己)
- 收到所有Server回復后,就計算出zxid最大的那個Server,并將這個Server相關信息設置成下一次要投票的Server
- 計算這過程中獲得票數最大的server為勝者,如果獲勝者的票數超過半數,則該server被選為leader。否則,繼續這個過程,知道leader被選出來
- leader就會開始鄧艾server鏈接
- Follower鏈接leader將最大的zxid發送給leader
- Leader根據fillower的zxid確定同步點
- 完成同步后通知follow,已經成為uptodate狀態
- Follower收到uptodate消息后,又可以重新接受client的請求進行服務了
應用場景1-統一命名服務
- 分布式應用中,通常需要有一套完整的命名規則,既能夠產生唯一的名稱又便于人識別和記住,通常情況下用樹形結構是一個理想的選擇,樹形的名稱結構是一個有層次的目錄結構,即對人友好又不會重復。
- Name Service是Zookeeper內置的功能,只要調用ZookeeperApi就能實現,如調用create接口就可以很容易創建一個目錄節點從而得到一個全局唯一的path,這個path就可以作為一個名稱。
- 阿里的分布式服務框架Dubbo中使用Zookeeper來作其命名服務,維護全局的服務地址列表:
應用場景2-配置管理
- 配置管理在分布式應用環境中很常見,例如同一個應用系統需要多臺PCServer運行,但是他們運行的應用系統的某些配置項是相同的,如果需要修改這些相同的配置,那么必須同時修改每臺云溪這個應用系統的PCServer,這樣就非常麻煩而且容易出錯
- 將配置信息保存在Zookeeper的某個目錄節點中,然后將所有需要修改的應用機器監控配置信息的狀態,一旦配置信息變化,每臺機器就會收到Zookeeper的通知,然后從Zookeeper獲取新的配置信息應用到系統中。
應用場景3-集群管理
- 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目錄節點,是一個有序的臨時節點,我們可以選出當前最小編號的Server是Master,加入這個最小編號Server死去,由于是Ephemeral節點,死去的Server對應的節點也會被刪掉,所以當前的節點列表中會出現另外一個最小編號節點,我們就選這個為當前Master,這就實現動態選擇Master,避免了傳統意義上單Master容易出現單節點故障問題。
- 規定最小編號的為Master,所以我們水Servers節點做監控的時候,得到服務器列表,只要所有集群機器邏輯認為最小編號節點為master,那么master就被選出
- 這個master宕機znode就刪除,新列表推送新的列表,在選出最小編號master,這樣就動態master選舉
- LeaderElection關鍵代碼
應用場景4-共享鎖
- 共享鎖在同一個進程中很容易實現,但是在跨JVM,不同Server之間就不好實現。Zookeeper卻很容易實現這個功能,實現方式也是需要獲得鎖的Server創建一個EPHEMERAL_SEQUENTIAL目錄節點(有序臨時節點),然后調用getChildren方法獲取當前目錄節點列表最小的目錄節點是不是就是自己創建的目錄節點,如果正是自己創建的,那么他就獲得這個鎖,如果不是那么它就調用exists(String path,boolean watch)方法并且監控Zookeeper生目錄節點列表的變化,一直到自己創建的節點是列表中最小編號的目錄節點,從而獲得鎖,釋放鎖很簡單,只要刪除簽名它自己所創建的目錄節點就行了
- 同步鎖關鍵代碼如下:
應用場景5-隊列管理
- Zookeeper可以處理兩種類型的隊列:
- 當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到大,這種是同步隊列
- 隊列按照FIFO方式進行入隊和出隊操作,例如,實現生產者消費者模型。
- 創建一個父目錄/synchronizing,每個成員都監控目錄/synchronizing/start是否存在,然后每個成員都加入這個隊列(創建/synchronizing/member_i的臨時目錄節點),然后每個成員獲取/synchronizing目錄的所有目錄節點,判斷i的值是否已經是成員的個數,如果小于成員的個數等待/synchronizing/start的出現,如果相等就創建/synchronizing/start
- 同步隊列代碼:
- 當隊列沒有滿進入wait,然后一直等待watch的通知,watch的代碼如下
- FIFO隊列用Zookeeper實現思路:
- 在特定目錄下創建SEQUENTIAL類型(有序類型)的目錄/queue_i,這樣就能保證所有成員入隊列都有編號,出隊了時通過getChildren方法可以返回當前所有的隊列中的元素,然后消費其中最小的一個,這樣就保證FIFO
- 生產者代碼:
- 消費者代碼
應用場景6-負載均衡
- 這里的負載均衡是指的軟負載均衡。分布式系統中,都是多服務集群部署。服務消費者需要在集群中選擇一個來執行相關業務,就去比較經典的生產者消費者問題。
- 消息中間件中發布者和訂閱者的負載均衡,linkedin開源的kafkaMQ和阿里開源的metaq都是zookeeper來做負載均衡,這里以metaq為案例如下:
- 生產者負載均衡:metaq發送消息時候,生產者在發送消息的時候必須選擇一臺broker上的一個分區來發送消息,因此metaq在運行過程中會吧broker和對應的分區信息全部注冊到ZK指定節點上,默認的策略是一個依次輪詢的過程,生產者在通過ZK獲取分區列表后,會按照brokerid和partition的順序排列組織成一個有序的分區列表,發送的時候,按照從頭到位循環往復的方式選擇一個分區來發送消息。
- 消費負載均衡:在消費過程中,一個消費者會消費一個或多個分區中的消息,但是一個分區只會由一個消費者來消費。MetaQ的消費策略是:
- 每個分區針對同一個group只掛載一個消費者
- 如果同一個group的消費者數目大于分區數目,則有部分消費者需要額外承擔消費任務
- 如果同一個group的消費者數目小于分區數目,則又部分消費者需要額外承擔消費任務。
- 在某個消費者故障或者重啟等情況下,其他消費者會感知到這一個變化(通過Zookeeper watch 消費者列表),然后重新進行負載均衡,保證所有分區都有消費者進行消費。
總結
- Zookeeper作為Hadoop項目中子項目,是Hadoop集群管理一個必不可少的模塊,主要用來控制集群中數量,如他管理Hadoop集群中NameNode,還有Hbase中Master Election,Server之間狀態同步等。
- Zookeeper提供了一套很好的分布式集群管理機制,就是他這種基于層次型的目錄樹的數據結構,并對樹中節點進行有效管理,從而可以設計出多種多樣的分布式數據管理模型。
下一篇Zookeeper理解—ZAB協議
總結
以上是生活随笔為你收集整理的zookeeper理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java调优方法,jvm监控工具
- 下一篇: 牛角刮痧板哪种牛角最好