Zookeeper那些事

1、 什麼是Zookeeper

Zookeeper 是 Google 的 Chubby一個開源的實現,是 Hadoop 的分佈式協調服務java

它包含一個簡單的原語集,分佈式應用程序能夠基於它實現同步服務,配置維護和命名服務等node

 

 

2、  爲何使用Zookeeper?

大部分分佈式應用須要一個主控、協調器或控制器來管理物理分佈的子進程(如資源、任務分配等)算法

目前,大部分應用須要開發私有的協調程序,缺少一個通用的機制apache

協調程序的反覆編寫浪費,且難以造成通用、伸縮性好的協調器服務器

ZooKeeper:提供通用的分佈式鎖服務,用以協調分佈式應用網絡

3、  Zookeeper能幫咱們作什麼?

Hadoop2.0,使用Zookeeper的事件處理確保整個集羣只有一個活躍的NameNode,存儲配置信息等.session

HBase,使用Zookeeper的事件處理確保整個集羣只有一個HMaster,察覺HRegionServer聯機和宕機,存儲訪問控制列表等.數據結構

4、Zookeeper的特性

Zookeeper是簡單的分佈式

Zookeeper是富有表現力的oop

Zookeeper具備高可用性

Zookeeper採用鬆耦合交互方式

Zookeeper是一個資源庫

5、Zookeeper的安裝和配置(單機模式)

一、下載ZooKeeper:

http://labs.renren.com/apache-mirror/zookeeper/zookeeper-3.4.3/zookeeper-3.4.3.tar.gz

解壓:tar xzf zookeeper-3.4.3.tar.gz/2

二、在conf目錄下建立一個配置文件zoo.cfg

  1. tickTime=2000  
  2. dataDir=/Users/zdandljb/zookeeper/data  
  3. dataLogDir=/Users/zdandljb/zookeeper/dataLog          
  4.   
  5. clientPort=2181  

三、啓動ZooKeeper的Server

sh bin/zkServer.sh start, 若是想要關閉,輸入:zkServer.sh stop

6、Zookeeper的安裝和配置(集羣模式)

一、建立myid文件:

server1機器的內容爲:1

server2機器的內容爲:2

server3機器的內容爲:3

二、在conf目錄下建立一個配置文件zoo.cfg

  1. tickTime=2000  
  2. dataDir=/Users/zdandljb/zookeeper/data  
  3. dataLogDir=/Users/zdandljb/zookeeper/dataLog          
  4.   
  5. clientPort=2181                                  
  6.   
  7. initLimit=5                                       
  8.   
  9. syncLimit=2                                                 
  10.   
  11. server.1=server1:2888:3888                                      
  12.   
  13. server.2=server2:2888:3888                                     
  14.   
  15. server.3=server3:2888:3888  

7、Zookeeper的安裝和配置(僞集羣模式)

一、建了3個文件夾,server1 server2 server3,而後每一個文件夾裏面解壓一個zookeeper的下載包

二、進入data目錄,建立一個myid的文件,裏面寫入一個數字,server1,就寫一個1,server2對應myid文件就寫入2,server3對應myid文件就寫個3

三、在conf目錄下建立一個配置文件zoo.cfg

 
  1. tickTime=2000  
  2.        dataDir=/Users/zdandljb/zookeeper/data  
  3.        dataLogDir=xxx/zookeeper/server1/           
  4.   
  5. clientPort=2181                                             
  6.   
  7. initLimit=5                                       
  8.   
  9. syncLimit=2                                                
  10.   
  11. server.1=server1:2888:3888                              
  12.   
  13. server.2=server2:2888:3888                                    
  14.   
  15. server.3=server3:2888:3888  

8、Zookeeper的數據模型

層次化的目錄結構,命名符合常規文件系統規範

每一個節點在zookeeper中叫作znode,而且其有一個惟一的路徑標識

節點Znode能夠包含數據和子節點,可是EPHEMERAL類型的節點不能有子節點

Znode中的數據能夠有多個版本,好比某一個路徑下存有多個數據版本,那麼查詢這個路徑下的數據就須要帶上版本

客戶端應用能夠在節點上設置監視器

節點不支持部分讀寫,而是一次性完整讀寫

9、Zookeeper的節點

Znode有兩種類型,短暫的(ephemeral)和持久的(persistent)

Znode的類型在建立時肯定而且以後不能再修改

短暫znode的客戶端會話結束時,zookeeper會將該短暫znode刪除,短暫znode不能夠有子節點

持久znode不依賴於客戶端會話,只有當客戶端明確要刪除該持久znode時纔會被刪除

Znode有四種形式的目錄節點,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL

10、Zookeeper的角色

領導者(leader),負責進行投票的發起和決議,更新系統狀態

學習者(learner),包括跟隨者(follower)和觀察者(observer),follower用於接受客戶端請求並向客戶端返回結果,在選主過程當中參與投票Observer能夠接受客戶端鏈接,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態,observer的目的是爲了擴展系統,提升讀取速度

客戶端(client),請求發起方

11、Zookeeper的順序號

建立znode時設置順序標識,znode名稱後會附加一個值

順序號是一個單調遞增的計數器,由父節點維護

在分佈式系統中,順序號能夠被用於爲全部的事件進行全局排序,這樣客戶端能夠經過順序號推斷事件的順序

12、Zookeeper的讀寫機制

Zookeeper是一個由多個server組成的集羣

一個leader,多個follower

每一個server保存一份數據副本

全局數據一致

分佈式讀寫

更新請求轉發,由leader實施

十3、Zookeeper的保證

更新請求順序進行,來自同一個client的更新請求按其發送順序依次執行

數據更新原子性,一次數據更新要麼成功,要麼失敗

全局惟一數據視圖,client不管鏈接到哪一個server,數據視圖都是一致的

實時性,在必定事件範圍內,client能讀到最新數據

十4、Zookeeper的API接口

  1. String create(String path, byte[] data,List<ACL> acl, CreateMode createMode)  
  2.   
  3. Stat exists(String path, boolean watch)  
  4.   
  5. void delete(String path, int version)  
  6.   
  7. List<String> getChildren(String path, boolean watch)  
  8.   
  9. List<String> getChildren(String path, boolean watch)  
  10.   
  11. Stat setData(String path, byte[] data, int version)  
  12.   
  13. byte[] getData(String path, boolean watch, Stat stat)  
  14.   
  15. void addAuthInfo(String scheme, byte[] auth)  
  16.   
  17. Stat setACL(String path, List<ACL> acl,int version)  
  18.   
  19. List<ACL> getACL(String path, Stat stat)   

十5、觀察(watcher)

Watcher 在 ZooKeeper 是一個核心功能,Watcher 能夠監控目錄節點的數據變化以及子目錄的變化,一旦這些狀態發生變化,服務器就會通知全部設置在這個目錄節點上的 Watcher,從而每一個客戶端都很快知道它所關注的目錄節點的狀態發生變化,而作出相應的反應

能夠設置觀察的操做:exists,getChildren,getData

能夠觸發觀察的操做:create,delete,setData

十六寫操做與zookeeper內部事件的對應關係

 

 

十7、zookeeper內部事件與watcher的對應關係

 

 

十8、 寫操做與watcher的對應關係

 

 

十9、ACL

每一個znode被建立時都會帶有一個ACL列表,用於決定誰能夠對它執行何種操做

 

身份驗證模式有三種:

digest:用戶名,密碼

host:經過客戶端的主機名來識別客戶端

ip: 經過客戶端的ip來識別客戶端

new ACL(Perms.READ,newId("host","example.com"));

                   這個ACL對應的身份驗證模式是host,符合該模式的身份是example.com,權限的組合是:READ

二10、Znode的節點狀態

 

每一個ACL都是身份驗證模式、符合該模式的一個身份和一組權限的組合

二11、 Zookeeper工做原理

Zookeeper的核心是原子廣播,這個機制保證了各個server之間的同步。實現這個機制的協議叫作Zab協議。Zab協議有兩種模式,它們分別是恢復模式和廣播模式。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數server的完成了和leader的狀態同步之後,恢復模式就結束了。狀態同步保證了leader和server具備相同的系統狀態。

一旦leader已經和多數的follower進行了狀態同步後,他就能夠開始廣播消息了,即進入廣播狀態。這時候當一個server加入zookeeper服務中,它會在恢復模式下啓動,發現leader,並和leader進行狀態同步。待到同步結束,它也參與消息廣播。Zookeeper服務一直維持在Broadcast狀態,直到leader崩潰了或者leader失去了大部分的followers支持。

廣播模式須要保證proposal被按順序處理,所以zk採用了遞增的事務id號(zxid)來保證。全部的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64爲的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch。低32位是個遞增計數。

當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式須要從新選舉出一個新的leader,讓全部的server都恢復到一個正確的狀態。

二12、Leader選舉

首先看一下選舉的過程,zk的實現中用了基於paxos算法(主要是fastpaxos)的實現。具體以下;此外恢復模式下,若是是從新剛從崩潰狀態恢復的或者剛啓動的的server還會從磁盤快照中恢復數據和會話信息。(zk會記錄事務日誌並按期進行快照,方便在恢復時進行狀態恢復)

每一個Server啓動之後都詢問其它的Server它要投票給誰。

對於其餘server的詢問,server每次根據本身的狀態都回複本身推薦的leader的id和上一次處理事務的zxid(系統啓動時每一個server都會推薦本身)

收到全部Server回覆之後,就計算出zxid最大的哪一個Server,並將這個Server相關信息設置成下一次要投票的Server。

計算這過程當中得到票數最多的的sever爲獲勝者,若是獲勝者的票數超過半數,則改server被選爲leader。不然,繼續這個過程,直到leader被選舉出來。

leader就會開始等待server鏈接

Follower鏈接leader,將最大的zxid發送給leader

Leader根據follower的zxid肯定同步點

完成同步後通知follower 已經成爲uptodate狀態

Follower收到uptodate消息後,又能夠從新接受client的請求進行服務了


 

Observing: 觀察狀態,這時候observer會觀察leader是否有改變,而後同步leader的狀態;Following:  跟隨狀態,接收leader的proposal ,進行投票。並和leader進行狀態同步

 

 

Looking: 尋找狀態,這個狀態不知道誰是leader,會發起leader選舉;Leading:    領導狀態,對Follower的投票進行決議,將狀態和follower進行同步

二十3、Zookeeper示例代碼

 

輸出的結果以下:

已經觸發了 None 事件!

testRootData   [testChildPathOne]

目錄節點狀態:[5,5,1281804532336,1281804532336,0,1,0,0,12,1,6]

已經觸發了NodeChildrenChanged 事件!

testChildDataTwo

已經觸發了NodeDeleted 事件!

已經觸發了NodeDeleted 事件!

二十4、應用場景

應用場景1: 統一命名服務

n  分佈式應用中,一般須要有一套完整的命名規則,既可以產生惟一的名稱又便於人識別和記住,一般狀況下用樹形的名稱結構是一個理想的選擇,樹形的名稱結構是一個有層次的目錄結構,既對人友好又不會重複。

n  Name Service 是 Zookeeper 內置的功能,只要調用 Zookeeper 的 API 就能實現

應用場景2: 配置管理

n  配置的管理在分佈式應用環境中很常見,例如同一個應用系統須要多臺 PCServer 運行,可是它們運行的應用系統的某些配置項是相同的,若是要修改這些相同的配置項,那麼就必須同時修改每臺運行這個應用系統的 PC Server,這樣很是麻煩並且容易出錯。

n  將配置信息保存在 Zookeeper 的某個目錄節點中,而後將全部須要修改的應用機器監控配置信息的狀態,一旦配置信息發生變化,每臺應用機器就會收到 Zookeeper 的通知,而後從 Zookeeper 獲取新的配置信息應用到系統中。

Zookeeper很容易實現這種集中式的配置管理,好比將APP1的全部配置配置到/APP1 znode下,APP1全部機器一啓動就對/APP1這個節點進行監控(zk.exist(「/APP1″,true)),而且實現回調方法 Watcher,那麼在zookeeper上/APP1 znode節點下數據發生變化的時候,每一個機器都會收到通知,Watcher方法將會被執行,那麼應用再取下數據便可 (zk.getData(「/APP1″,false,null));

 

 

應用場景3: 集羣管理

n  Zookeeper 可以很容易的實現集羣管理的功能,若有多臺 Server 組成一個服務集羣,那麼必需要一個「總管」知道當前集羣中每臺機器的服務狀態,一旦有機器不能提供服務,集羣中其它集羣必須知道,從而作出調整從新分配服務策略。一樣當增長集羣的服務能力時,就會增長一臺或多臺 Server,一樣也必須讓「總管」知道。

n  Zookeeper 不只可以維護當前的集羣中機器的服務狀態,並且可以選出一個「總管」,讓這個總管來管理集羣,這就是 Zookeeper 的另外一個功能 Leader Election。

應用集羣中,咱們經常須要讓每個機器知道集羣中(或依賴的其餘某一個集羣)哪些機器是活着的,而且在集羣機器由於宕機,網絡斷鏈等緣由可以不在人工介入的狀況下迅速通知到每個機器。Zookeeper一樣很容易實現這個功能,好比我在zookeeper服務器端有一個znode叫/APP1SERVERS,那麼集羣中每個機器啓動 的時候都去這個節點下建立一個EPHEMERAL類型的節點,好比server1建立/APP1SERVERS/SERVER1(可使用ip,保證不重 復),server2建立/APP1SERVERS/SERVER2,而後SERVER1和SERVER2都watch /APP1SERVERS這個父節點,那麼也就是這個父節點下數據或者子節點變化都會通知對該節點進行watch的客戶端。由於EPHEMERAL類型節 點有一個很重要的特性,就是客戶端和服務器端鏈接斷掉或者session過時就會使節點消失,那麼在某一個機器掛掉或者斷鏈的時候,其對應的節點就會消失,而後集羣中全部對/APP1SERVERS進行watch的客戶端都會收到通知,而後取得最新列表便可。

 

 

Zookeeper 如何實現 Leader Election,也就是選出一個 Master Server;另外有一個應用場景就是集羣選master,一旦master掛掉可以立刻能從slave中選出一個master,實現步驟和前者同樣,只是機器在啓動的 時候在APP1SERVERS建立的節點類型變爲EPHEMERAL_SEQUENTIAL類型,這樣每一個節點會自動被編號

  1. zk.create("/testRootPath/testChildPath1","1".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  2.   
  3. zk.create(「/testRootPath/testChildPath2」,「2」.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  4.   
  5. zk.create("/testRootPath/testChildPath3","3".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  6.   
  7. zk.create("/testRootPath/testChildPath4","4".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);  
  8.   
  9. System.out.println(zk.getChildren("/testRootPath",false));  
  10.   
  11. 打印結果:[testChildPath10000000000,testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]  

規定編號最小的爲master,因此當咱們對SERVERS節點作監控的時候,獲得服務器列表,只要全部集羣機器邏輯認爲最小編號節點爲master,那麼master就被選出,而這個master宕機的時候,相應的znode會消失,而後新的服務器列表就被推送到客戶端,而後每一個節點邏輯認爲最小編號節點爲master,這樣就作到動態master選舉。

應用場景4:共享鎖

共享鎖在同一個進程中很容易實現,可是在跨進程或者在不一樣 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。

 

二十5、總結

Zookeeper 做爲 Hadoop 項目中的一個子項目,是 Hadoop 集羣管理的一個必不可少的模塊,它主要用來控制集羣中的數據,如它管理 Hadoop 集羣中的 NameNode,還有 Hbase 中 Master Election、Server 之間狀態同步等。

Zoopkeeper提供了一套很好的分佈式集羣管理的機制,就是它這種基於層次型的目錄樹的數據結構,並對樹中的節點進行有效管理,從而能夠設計出多種多樣的分佈式的數據管理模型

轉載:http://blog.csdn.net/l1028386804/article/details/52226265

相關文章
相關標籤/搜索