<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 28, comments - 37, trackbacks - 0, articles - 0

    zookeeper 簡介

    Posted on 2011-10-29 20:18 俞靈 閱讀(5212) 評論(1)  編輯  收藏

    本周末學習zookeeper,原理和安裝配置

    本文參考: http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/

    http://zookeeper.apache.org/

     

    Zookeeper 作為一個分布式的服務框架,主要用來解決分布式集群中應用系統(tǒng)的一致性問題,它能提供基于類似于文件系統(tǒng)的目錄節(jié)點樹方式的數(shù)據(jù)存儲,但是 Zookeeper 并不是用來專門存儲數(shù)據(jù)的,它的作用主要是用來維護和監(jiān)控你存儲的數(shù)據(jù)的狀態(tài)變化。通過監(jiān)控這些數(shù)據(jù)狀態(tài)的變化,從而可以達到基于數(shù)據(jù)的集群管理。

    Zookeeper安裝和配置比較簡單,可以參考官網(wǎng).

    數(shù)據(jù)模型

    Zookeeper 會維護一個具有層次關系的數(shù)據(jù)結構,它非常類似于一個標準的文件系統(tǒng),如圖 1 所示:


    1 Zookeeper 數(shù)據(jù)結構

    Zookeeper 這種數(shù)據(jù)結構有如下這些特點:

    1. 每個子目錄項如 NameService 都被稱作為 znode,這個 znode 是被它所在的路徑唯一標識,如 Server1 這個 znode 的標識為 /NameService/Server1
    2. znode 可以有子節(jié)點目錄,并且每個 znode 可以存儲數(shù)據(jù),注意 EPHEMERAL 類型的目錄節(jié)點不能有子節(jié)點目錄
    3. znode 是有版本的,每個 znode 中存儲的數(shù)據(jù)可以有多個版本,也就是一個訪問路徑中可以存儲多份數(shù)據(jù)
    4. znode 可以是臨時節(jié)點,一旦創(chuàng)建這個 znode 的客戶端與服務器失去聯(lián)系,這個 znode 也將自動刪除,Zookeeper 的客戶端和服務器通信采用長連接方式,每個客戶端和服務器通過心跳來保持連接,這個連接狀態(tài)稱為 session,如果 znode 是臨時節(jié)點,這個 session 失效,znode 也就刪除了
    5. znode 的目錄名可以自動編號,如 App1 已經(jīng)存在,再創(chuàng)建的話,將會自動命名為 App2
    6. znode 可以被監(jiān)控,包括這個目錄節(jié)點中存儲的數(shù)據(jù)的修改,子節(jié)點目錄的變化等,一旦變化可以通知設置監(jiān)控的客戶端,這個是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于這個特性實現(xiàn)的,后面在典型的應用場景中會有實例介紹

     

    ZooKeeper 典型的應用場景

    Zookeeper 從設計模式角度來看,是一個基于觀察者模式設計的分布式服務管理框架,它負責存儲和管理大家都關心的數(shù)據(jù),然后接受觀察者的注冊,一旦這些數(shù)據(jù)的狀態(tài)發(fā)生 變化,Zookeeper 就將負責通知已經(jīng)在 Zookeeper 上注冊的那些觀察者做出相應的反應,從而實現(xiàn)集群中類似 Master/Slave 管理模式,關于 Zookeeper 的詳細架構等內(nèi)部細節(jié)可以閱讀 Zookeeper 的源碼

    下面詳細介紹這些典型的應用場景,也就是 Zookeeper 到底能幫我們解決那些問題?下面將給出答案。

    統(tǒng)一命名服務(Name Service)

    分布式應用中,通常需要有一套完整的命名規(guī)則,既能夠產(chǎn)生唯一的名稱又便于人識別和記住,通常情況下用樹形的名稱結構是一個理想的選擇,樹形 的名稱結構是一個有層次的目錄結構,既對人友好又不會重復。說到這里你可能想到了 JNDI(Java Naming and Directory Interface,Java命名和目錄接口,是一組在Java應用中訪問命名和目錄服務的API),沒錯 Zookeeper 的 Name Service 與 JNDI 能夠完成的功能是差不多的,它們都是將有層次的目錄結構關聯(lián)到一定資源上,但是 Zookeeper 的 Name Service 更加是廣泛意義上的關聯(lián),也許你并不需要將名稱關聯(lián)到特定資源上,你可能只需要一個不會重復名稱,就像數(shù)據(jù)庫中產(chǎn)生一個唯一的數(shù)字主鍵一樣。

    Name Service 已經(jīng)是 Zookeeper 內(nèi)置的功能,你只要調(diào)用 Zookeeper 的 API 就能實現(xiàn)。如調(diào)用 create 接口就可以很容易創(chuàng)建一個目錄節(jié)點。

    配置管理(Configuration Management

    配置的管理在分布式應用環(huán)境中很常見,例如同一個應用系統(tǒng)需要多臺 PC Server 運行,但是它們運行的應用系統(tǒng)的某些配置項是相同的,如果要修改這些相同的配置項,那么就必須同時修改每臺運行這個應用系統(tǒng)的 PC Server,這樣非常麻煩而且容易出錯。

    像這樣的配置信息完全可以交給 Zookeeper 來管理,將配置信息保存在 Zookeeper 的某個目錄節(jié)點中,然后將所有需要修改的應用機器監(jiān)控配置信息的狀態(tài),一旦配置信息發(fā)生變化,每臺應用機器就會收到 Zookeeper 的通知,然后從 Zookeeper 獲取新的配置信息應用到系統(tǒng)中。


    2. 配置管理結構圖

    集群管理(Group Membership

    Zookeeper 能夠很容易的實現(xiàn)集群管理的功能,如有多臺 Server 組成一個服務集群,那么必須要一個“總管”知道當前集群中每臺機器的服務狀態(tài),一旦有機器不能提供服務,集群中其它集群必須知道,從而做出調(diào)整重新分配服 務策略。同樣當增加集群的服務能力時,就會增加一臺或多臺 Server,同樣也必須讓“總管”知道。

    Zookeeper 不僅能夠幫你維護當前的集群中機器的服務狀態(tài),而且能夠幫你選出一個“總管”,讓這個總管來管理集群,這就是 Zookeeper 的另一個功能 Leader Election。

    它們的實現(xiàn)方式都是在 Zookeeper 上創(chuàng)建一個 EPHEMERAL 類型的目錄節(jié)點,然后每個 Server 在它們創(chuàng)建目錄節(jié)點的父目錄節(jié)點上調(diào)用 getChildren(String path, boolean watch) 方法并設置 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é)點,所以它是個 EPHEMERAL_SEQUENTIAL 目錄節(jié)點。之所以它是 EPHEMERAL_SEQUENTIAL 目錄節(jié)點,是因為我們可以給每臺 Server 編號,我們可以選擇當前是最小編號的 Server 為 Master,假如這個最小編號的 Server 死去,由于是 EPHEMERAL 節(jié)點,死去的 Server 對應的節(jié)點也被刪除,所以當前的節(jié)點列表中又出現(xiàn)一個最小編號的節(jié)點,我們就選擇這個節(jié)點為當前 Master。這樣就實現(xiàn)了動態(tài)選擇 Master,避免了傳統(tǒng)意義上單 Master 容易出現(xiàn)單點故障的問題。


    3. 集群管理結構圖

    這部分的示例代碼如下,完整的代碼請看源代碼:


    清單 3. Leader Election 關鍵代碼

                                   
     void findLeader() throws InterruptedException { 
            byte[] leader = null; 
            try { 
                leader = zk.getData(root + "/leader", true, null); 
            } catch (Exception e) { 
                logger.error(e); 
            } 
            if (leader != null) { 
                following(); 
            } else { 
                String newLeader = null; 
                try { 
                    byte[] localhost = InetAddress.getLocalHost().getAddress(); 
                    newLeader = zk.create(root + "/leader", localhost, 
                    ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); 
                } catch (Exception e) { 
                    logger.error(e); 
                } 
                if (newLeader != null) { 
                    leading(); 
                } else { 
                    mutex.wait(); 
                } 
            } 
        } 

     

    共享鎖(Locks)

    共享鎖在同一個進程中很容易實現(xiàn),但是在跨進程或者在不同 Server 之間就不好實現(xiàn)了。Zookeeper 卻很容易實現(xiàn)這個功能,實現(xiàn)方式也是需要獲得鎖的 Server 創(chuàng)建一個 EPHEMERAL_SEQUENTIAL 目錄節(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é)點就行了。


    4. Zookeeper 實現(xiàn) Locks 的流程圖

    同步鎖的實現(xiàn)代碼如下,完整的代碼請看源代碼:


    清單 4. 同步鎖的關鍵代碼

                                   
     void getLock() throws KeeperException, InterruptedException{ 
            List<String> list = zk.getChildren(root, false); 
            String[] nodes = list.toArray(new String[list.size()]); 
            Arrays.sort(nodes); 
            if(myZnode.equals(root+"/"+nodes[0])){ 
                doAction(); 
            } 
            else{ 
                waitForLock(nodes[0]); 
            } 
        } 
        void waitForLock(String lower) throws InterruptedException, KeeperException {
            Stat stat = zk.exists(root + "/" + lower,true); 
            if(stat != null){ 
                mutex.wait(); 
            } 
            else{ 
                getLock(); 
            } 
        } 

     

    隊列管理

    Zookeeper 可以處理兩種類型的隊列:

    1. 當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達,這種是同步隊列。
    2. 隊列按照 FIFO 方式進行入隊和出隊操作,例如實現(xiàn)生產(chǎn)者和消費者模型。

    同步隊列用 Zookeeper 實現(xiàn)的實現(xiàn)思路如下:

    創(chuàng)建一個父目錄 /synchronizing,每個成員都監(jiān)控標志(Set Watch)位目錄 /synchronizing/start 是否存在,然后每個成員都加入這個隊列,加入隊列的方式就是創(chuàng)建 /synchronizing/member_i 的臨時目錄節(jié)點,然后每個成員獲取 / synchronizing 目錄的所有目錄節(jié)點,也就是 member_i。判斷 i 的值是否已經(jīng)是成員的個數(shù),如果小于成員個數(shù)等待 /synchronizing/start 的出現(xiàn),如果已經(jīng)相等就創(chuàng)建 /synchronizing/start。

    用下面的流程圖更容易理解:


    5. 同步隊列流程圖

    同步隊列的關鍵代碼如下,完整的代碼請看附件:


    清單 5. 同步隊列

                                   
     void addQueue() throws KeeperException, InterruptedException{ 
            zk.exists(root + "/start",true); 
            zk.create(root + "/" + name, new byte[0], Ids.OPEN_ACL_UNSAFE, 
            CreateMode.EPHEMERAL_SEQUENTIAL); 
            synchronized (mutex) { 
                List<String> list = zk.getChildren(root, false); 
                if (list.size() < size) { 
                    mutex.wait(); 
                } else { 
                    zk.create(root + "/start", new byte[0], Ids.OPEN_ACL_UNSAFE,
                     CreateMode.PERSISTENT); 
                } 
            } 
     } 

     

    當隊列沒滿是進入 wait(),然后會一直等待 Watch 的通知,Watch 的代碼如下:

     public void process(WatchedEvent event) { 
            if(event.getPath().equals(root + "/start") &&
             event.getType() == Event.EventType.NodeCreated){ 
                System.out.println("得到通知"); 
                super.process(event); 
                doAction(); 
            } 
        } 

     

    FIFO 隊列用 Zookeeper 實現(xiàn)思路如下:

    實現(xiàn)的思路也非常簡單,就是在特定的目錄下創(chuàng)建 SEQUENTIAL 類型的子目錄 /queue_i,這樣就能保證所有成員加入隊列時都是有編號的,出隊列時通過 getChildren( ) 方法可以返回當前所有的隊列中的元素,然后消費其中最小的一個,這樣就能保證 FIFO

    下面是生產(chǎn)者和消費者這種隊列形式的示例代碼,完整的代碼請看附件:


    清單 6. 生產(chǎn)者代碼

                                   
     boolean produce(int i) throws KeeperException, InterruptedException{ 
            ByteBuffer b = ByteBuffer.allocate(4); 
            byte[] value; 
            b.putInt(i); 
            value = b.array(); 
            zk.create(root + "/element", value, ZooDefs.Ids.OPEN_ACL_UNSAFE, 
                        CreateMode.PERSISTENT_SEQUENTIAL); 
            return true; 
        } 



    清單 7. 消費者代碼

                                   
     int consume() throws KeeperException, InterruptedException{ 
            int retvalue = -1; 
            Stat stat = null; 
            while (true) { 
                synchronized (mutex) { 
                    List<String> list = zk.getChildren(root, true); 
                    if (list.size() == 0) { 
                        mutex.wait(); 
                    } else { 
                        Integer min = new Integer(list.get(0).substring(7)); 
                        for(String s : list){ 
                            Integer tempValue = new Integer(s.substring(7)); 
                            if(tempValue < min) min = tempValue; 
                        } 
                        byte[] b = zk.getData(root + "/element" + min,false, stat); 
                        zk.delete(root + "/element" + min, 0); 
                        ByteBuffer buffer = ByteBuffer.wrap(b); 
                        retvalue = buffer.getInt(); 
                        return retvalue; 
                    } 
                } 
            } 
     } 

     

    總結

    Zookeeper 作為 Hadoop 項目中的一個子項目,是 Hadoop 集群管理的一個必不可少的模塊,它主要用來控制集群中的數(shù)據(jù),如它管理 Hadoop 集群中的 NameNode,還有 Hbase 中 Master Election、Server 之間狀態(tài)同步等。

    本文介紹的 Zookeeper 的基本知識,以及介紹了幾個典型的應用場景。這些都是 Zookeeper 的基本功能,最重要的是 Zoopkeeper 提供了一套很好的分布式集群管理的機制,就是它這種基于層次型的目錄樹的數(shù)據(jù)結構,并對樹中的節(jié)點進行有效管理,從而可以設計出多種多樣的分布式的數(shù)據(jù)管 理模型,而不僅僅局限于上面提到的幾個常用應用場景。


    Feedback

    # re: zookeeper 簡介  回復  更多評論   

    2012-08-24 17:30 by 11111111
    牛人!!!!!!!

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 人人狠狠综合久久亚洲88| 成年女人男人免费视频播放| 亚洲国产人成中文幕一级二级| 亚洲中文字幕精品久久| 最新欧洲大片免费在线| 亚洲1区1区3区4区产品乱码芒果| 国产成人免费高清激情明星| 亚洲国产成a人v在线| 成视频年人黄网站免费视频| 亚洲AV男人的天堂在线观看| 青草草在线视频永久免费| 亚洲丰满熟女一区二区哦| 国产成人青青热久免费精品| 免费一级做a爰片久久毛片潮| 亚洲国产成人精品91久久久| 久久久久女教师免费一区| 久久久久亚洲AV成人无码| 狼群影院在线观看免费观看直播| 亚洲成人免费网站| 日本免费的一级v一片| 思思久久99热免费精品6| 亚洲成AV人在线播放无码| 精品福利一区二区三区免费视频| 亚洲熟妇久久精品| 亚洲国产成人久久一区久久| 水蜜桃视频在线观看免费播放高清 | 亚洲熟女精品中文字幕| 又粗又硬又黄又爽的免费视频 | 国产亚洲免费的视频看| 最近免费中文字幕大全高清大全1| 亚洲色图.com| 免费一级毛片在级播放| 国产午夜无码精品免费看| 亚洲依依成人精品| 亚洲国产91精品无码专区| 91成人在线免费视频| 亚洲AV无码国产精品永久一区| 国产亚洲精品线观看动态图| 国产成人yy免费视频| 丰满妇女做a级毛片免费观看| 久久亚洲精品成人av无码网站|