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

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

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

    敏捷、分布式、ALM過程自動化、企業應用架構
    posts - 14, comments - 0, trackbacks - 0, articles - 1
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Zookeeper的學習總結

    Posted on 2012-05-15 11:02 一酌散千憂 閱讀(4835) 評論(0)  編輯  收藏 所屬分類: Hadoop 、企業架構

    Zookeeper的核心概念:

    ZNode

    Znode就是核心結構,Zookeeper服務中是由大量的Znode構成。Znode一般是由客戶端建立和修改,作為信息或標志的載體,甚至本身就是標志。

    Znode可以設置為持久(PERSISTENT)或臨時(EPHEMERAL),區別在于臨時的節點若斷開連接后就自動刪除。建立節點時可選擇是否使用序列號命名(SEQUENTIAL),若啟用則會自動在節點名后加入唯一序列編號。

    Session

    作為客戶端和Zookeeper服務之間交互的憑證。

    Watch

    當客戶端對節點信息進行查詢操作之后,可以選擇是否設置一個Watch。其作用就是當本次查詢的數據在服務器端發生變化之后,會對設置Watch的客戶端發送通知。一次發送之后,就將刪除該Watch,以后的變更或不再設置Watch則不會通知。

    ACLs

    節點的權限限制使用ACL,如增刪改查操作。

    Zookeeper的服務器安裝:

    1、下載對應版本號的tar.gz文件

    2、使用 tar xzvf zookeeper-3.4.2.tar.gz -C ./ 解壓

    3、設置,將conf/zoo.example.cfg復制到conf/zoo.cfg或者手動建立一個新的。

    4、啟動Zookeeper服務:bin/zkServer.sh start

    5、啟動客戶端連接:bin/zkCli.sh -server 127.0.0.1:2181(此處在本機,且使用了默認端口,且在Java環境中)

    6、使用命令:ls、get、set等。

    7、關閉Zookeeper服務:bin/zkServer.sh stop

    Zookeeper代碼編寫:

    代碼編寫部分比較簡單,因為暴露的接口很少,主要復雜在于項目如何使用節點以及節點信息。

    啟動Zookeeper服務之后,客戶端代碼進行節點的增刪,Watch的設置,內容的改查等。

    此處建議查看官方的《Programming with ZooKeeper - A basic tutorial》部分,當中舉了兩個例子來模擬分布式系統的應用。

    代碼基本沒有問題,唯一需要注意的就是:若之間按照原版進行調試時,有可能在調用

     Stat s = zk.exists(root, false);

    這句代碼時會出現一個異常,當中包括“KeeperErrorCode = ConnectionLoss for”。

    這個問題引起的原因可以看一下代碼

                    System.out.println("Starting ZK:");
                    zk 
    = new ZooKeeper(address, 3000this);
                    mutex 
    = new Integer(-1);
                    System.out.println(
    "Finished starting ZK: " + zk);

    最后一行有打印出Zookeeper目前的信息,若未修改的原代碼,此處的State應當是CONECTING。連接中的時候去驗證是否存在節點會報錯。解決的方法也很簡單,就是等到Zookeeper客戶端以及完全連接上服務器,State為CONECTED之后再進行其他操作。給出代碼示例:

    // 使用了倒數計數,只需要計數一次
    private CountDownLatch connectedSignal = new CountDownLatch(1); 
    SyncPrimitive(String address) {
        
    if(zk == null){
            
    try {
                System.out.println(
    "Starting ZK:");
                zk 
    = new ZooKeeper(address, 3000this);
                mutex 
    = new Integer(-1);
                connectedSignal.await(); 
    // 等待連接完成
                System.out.println("Finished starting ZK: " + zk);
            } 
    catch (IOException e) {
                System.out.println(e.toString());
                zk 
    = null;
            } 
    catch (InterruptedException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    //else mutex = new Integer(-1);
    }
    synchronized public void process(WatchedEvent event) {
        
    // 此處設立在Watch中會在狀態變化后觸發事件
        if (event.getState() == KeeperState.SyncConnected) {
            connectedSignal.countDown();
    // 倒數-1
        }
        
            
    synchronized (mutex) {
                
    //System.out.println("Process: " + event.getType());
                mutex.notify();
            }
    }

    這樣就可以正確運行代碼了。

    Zookeeper的應用場景及方式:

    此處是為引用,原地址為(http://rdc.taobao.com/team/jm/archives/1232 

    ZooKeeper是一個高可用的分布式數據管理與系統協調框架?;趯axos算法的實現,使該框架保證了分布式環境中數據的強一致性,也正是基于這樣的特性,使得zookeeper能夠應用于很多場景。網上對zk的使用場景也有不少介紹,本文將結合作者身邊的項目例子,系統的對zk的使用場景進行歸類介紹。 值得注意的是,zk并不是生來就為這些場景設計,都是后來眾多開發者根據框架的特性,摸索出來的典型使用方法。因此,也非常歡迎你分享你在ZK使用上的奇技淫巧。

    場景類別

    典型場景描述(ZK特性,使用方法)

    應用中的具體使用

    數據發布與訂閱

    發布與訂閱即所謂的配置管理,顧名思義就是將數據發布到zk節點上,供訂閱者動態獲取數據,實現配置信息的集中式管理和動態更新。例如全局的配置信息,地址列表等就非常適合使用。

    1. 索引信息和集群中機器節點狀態存放在zk的一些指定節點,供各個客戶端訂閱使用。2. 系統日志(經過處理后的)存儲,這些日志通常2-3天后被清除。 

    3. 應用中用到的一些配置信息集中管理,在應用啟動的時候主動來獲取一次,并且在節點上注冊一個Watcher,以后每次配置有更新,實時通知到應用,獲取最新配置信息。

    4. 業務邏輯中需要用到的一些全局變量,比如一些消息中間件的消息隊列通常有個offset,這個offset存放在zk上,這樣集群中每個發送者都能知道當前的發送進度。

    5. 系統中有些信息需要動態獲取,并且還會存在人工手動去修改這個信息。以前通常是暴露出接口,例如JMX接口,有了zk后,只要將這些信息存放到zk節點上即可。

    Name Service

    這個主要是作為分布式命名服務,通過調用zk的create node api,能夠很容易創建一個全局唯一的path,這個path就可以作為一個名稱。

     

    分布通知/協調

    ZooKeeper中特有watcher注冊與異步通知機制,能夠很好的實現分布式環境下不同系統之間的通知與協調,實現對數據變更的實時處理。使用方法通常是不同系統都對ZK上同一個znode進行注冊,監聽znode的變化(包括znode本身內容及子節點的),其中一個系統update了znode,那么另一個系統能夠收到通知,并作出相應處理。

    1. 另一種心跳檢測機制:檢測系統和被檢測系統之間并不直接關聯起來,而是通過zk上某個節點關聯,大大減少系統耦合。2. 另一種系統調度模式:某系統有控制臺和推送系統兩部分組成,控制臺的職責是控制推送系統進行相應的推送工作。管理人員在控制臺作的一些操作,實際上是修改了ZK上某些節點的狀態,而zk就把這些變化通知給他們注冊Watcher的客戶端,即推送系統,于是,作出相應的推送任務。 

    3. 另一種工作匯報模式:一些類似于任務分發系統,子任務啟動后,到zk來注冊一個臨時節點,并且定時將自己的進度進行匯報(將進度寫回這個臨時節點),這樣任務管理者就能夠實時知道任務進度。

    總之,使用zookeeper來進行分布式通知和協調能夠大大降低系統之間的耦合。

    分布式鎖

    分布式鎖,這個主要得益于ZooKeeper為我們保證了數據的強一致性,即用戶只要完全相信每時每刻,zk集群中任意節點(一個zk server)上的相同znode的數據是一定是相同的。鎖服務可以分為兩類,一個是保持獨占,另一個是控制時序。 

    所謂保持獨占,就是所有試圖來獲取這個鎖的客戶端,最終只有一個可以成功獲得這把鎖。通常的做法是把zk上的一個znode看作是一把鎖,通過create znode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。

    控制時序,就是所有視圖來獲取這個鎖的客戶端,最終都是會被安排執行,只是有個全局時序了。做法和上面基本類似,只是這里 /distribute_lock 已經預先存在,客戶端在它下面創建臨時有序節點(這個可以通過節點的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)。Zk的父節點(/distribute_lock)維持一份sequence,保證子節點創建的時序性,從而也形成了每個客戶端的全局時序。

     

    集群管理

    1. 集群機器監控:這通常用于那種對集群中機器狀態,機器在線率有較高要求的場景,能夠快速對集群中機器變化作出響應。這樣的場景中,往往有一個監控系統,實時檢測集群機器是否存活。過去的做法通常是:監控系統通過某種手段(比如ping)定時檢測每個機器,或者每個機器自己定時向監控系統匯報“我還活著”。 這種做法可行,但是存在兩個比較明顯的問題:1. 集群中機器有變動的時候,牽連修改的東西比較多。2. 有一定的延時。 

    利用ZooKeeper有兩個特性,就可以實時另一種集群機器存活性監控系統:a. 客戶端在節點 x 上注冊一個Watcher,那么如果 x 的子節點變化了,會通知該客戶端。b. 創建EPHEMERAL類型的節點,一旦客戶端和服務器的會話結束或過期,那么該節點就會消失。

    例如,監控系統在 /clusterServers 節點上注冊一個Watcher,以后每動態加機器,那么就往 /clusterServers 下創建一個 EPHEMERAL類型的節點:/clusterServers/{hostname}. 這樣,監控系統就能夠實時知道機器的增減情況,至于后續處理就是監控系統的業務了。
    2. Master選舉則是zookeeper中最為經典的使用場景了。

    在分布式環境中,相同的業務應用分布在不同的機器上,有些業務邏輯(例如一些耗時的計算,網絡I/O處理),往往只需要讓整個集群中的某一臺機器進行執行,其余機器可以共享這個結果,這樣可以大大減少重復勞動,提高性能,于是這個master選舉便是這種場景下的碰到的主要問題。

    利用ZooKeeper的強一致性,能夠保證在分布式高并發情況下節點創建的全局唯一性,即:同時有多個客戶端請求創建 /currentMaster 節點,最終一定只有一個客戶端請求能夠創建成功。

    利用這個特性,就能很輕易的在分布式環境中進行集群選取了。

    另外,這種場景演化一下,就是動態Master選舉。這就要用到 EPHEMERAL_SEQUENTIAL類型節點的特性了。

    上文中提到,所有客戶端創建請求,最終只有一個能夠創建成功。在這里稍微變化下,就是允許所有請求都能夠創建成功,但是得有個創建順序,于是所有的請求最終在ZK上創建結果的一種可能情況是這樣: /currentMaster/{sessionId}-1 , /currentMaster/{sessionId}-2 , /currentMaster/{sessionId}-3 ….. 每次選取序列號最小的那個機器作為Master,如果這個機器掛了,由于他創建的節點會馬上小時,那么之后最小的那個機器就是Master了。

    1. 在搜索系統中,如果集群中每個機器都生成一份全量索引,不僅耗時,而且不能保證彼此之間索引數據一致。因此讓集群中的Master來進行全量索引的生成,然后同步到集群中其它機器。2. 另外,Master選舉的容災措施是,可以隨時進行手動指定master,就是說應用在zk在無法獲取master信息時,可以通過比如http方式,向一個地方獲取master。

    分布式隊列

    隊列方面,我目前感覺有兩種,一種是常規的先進先出隊列,另一種是要等到隊列成員聚齊之后的才統一按序執行。對于第二種先進先出隊列,和分布式鎖服務中的控制時序場景基本原理一致,這里不再贅述。 

    第二種隊列其實是在FIFO隊列的基礎上作了一個增強。通常可以在 /queue 這個znode下預先建立一個/queue/num 節點,并且賦值為n(或者直接給/queue賦值n),表示隊列大小,之后每次有隊列成員加入后,就判斷下是否已經到達隊列大小,決定是否可以開始執行了。這種用法的典型場景是,分布式環境中,一個大任務Task A,需要在很多子任務完成(或條件就緒)情況下才能進行。這個時候,凡是其中一個子任務完成(就緒),那么就去 /taskList 下建立自己的臨時時序節點(CreateMode.EPHEMERAL_SEQUENTIAL),當 /taskList 發現自己下面的子節點滿足指定個數,就可以進行下一步按序進行處理了。

     

    主站蜘蛛池模板: 亚洲av永久无码一区二区三区| 噜噜噜亚洲色成人网站∨| 亚洲综合无码无在线观看| 亚洲免费黄色网址| 亚洲丝袜美腿视频| 最近免费中文字幕高清大全 | 亚洲av成人一区二区三区在线播放| 免费黄色网址网站| 亚洲不卡中文字幕| 老司机在线免费视频| 中文字幕精品三区无码亚洲 | 日韩在线观看免费完整版视频| 免费大香伊蕉在人线国产 | 亚洲一卡二卡三卡| 91精品免费在线观看| 亚洲乱码在线观看| 国产精品另类激情久久久免费| 国产精品日本亚洲777| 亚洲成年看片在线观看| 成人网站免费大全日韩国产| 久久久久久亚洲精品| 亚欧色视频在线观看免费| 亚洲AV无码无限在线观看不卡 | 香蕉97超级碰碰碰免费公| 国产成人精品日本亚洲网址 | 黄色片在线免费观看| 亚洲国产精品无码观看久久| 免费国产一级特黄久久| 国产日韩在线视频免费播放| 久久久久无码精品亚洲日韩 | 日本视频免费观看| 亚洲AV午夜成人片| **俄罗斯毛片免费| 国产精品亚洲专区无码牛牛| 青青草原亚洲视频| A在线观看免费网站大全| 日韩精品亚洲专区在线影视| 国产成人亚洲综合无码精品| 成人免费在线观看网站| 两个人的视频www免费| 亚洲sss综合天堂久久久|