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