大數(shù)據(jù) Zookeeper 介紹與簡單應(yīng)用

  1. Zookeeper 概述

    • Zookeeper 是一個分布式協(xié)調(diào)服務(wù)的開源框架。主要用來解決分布式集群中應(yīng)用系統(tǒng)的一致性問題。

    • Zookeeper 本質(zhì)上是一個分布式的小文件存儲系統(tǒng)。提供基于類似于文件系統(tǒng)的目錄樹方式的數(shù)據(jù)存儲缕允,并且可以對樹中的節(jié)點進行有效管理娶桦。從而用來維護和監(jiān)控你存儲的數(shù)據(jù)的狀態(tài)變化。通過監(jiān)控這些數(shù)據(jù)狀態(tài)的變化袖肥,從而可以達(dá)到基于數(shù)據(jù)的集群管理。

  2. Zookeeper 特性

    • 全局?jǐn)?shù)據(jù)一致:集群中每個服務(wù)器保存一份相同的數(shù)據(jù)副本振劳,client 無論連接到哪個服務(wù)器椎组,展示的數(shù)據(jù)都是一致的,這是最重要的特征澎迎;

    • 可靠性:如果消息被其中一臺服務(wù)器接受庐杨,那么將被所有的服務(wù)器接受。

    • 順序性:包括全局有序和偏序兩種

      • 全局有序是指如果在一臺服務(wù)器上消息 a 在消息 b 前發(fā)布夹供,則在所有 Server 上消息 a 都將在消息 b 前被發(fā)布灵份;

      • 偏序是指如果一個消息 b 在消息 a 后被同一個發(fā)送者發(fā)布,a 必將排在 b 前面哮洽。

    • 數(shù)據(jù)更新原子性:一次數(shù)據(jù)更新要么成功(半數(shù)以上節(jié)點成功)填渠,要么失敗,不存在中間狀態(tài)鸟辅;

    • 實時性:Zookeeper 保證客戶端將在一個時間間隔范圍內(nèi)獲得服務(wù)器的更新信息氛什,或者服務(wù)器失效的信息。

  3. Zookeeper 集群角色

    • Leader

      • Zookeeper 集群工作的核心

      • 事務(wù)請求(寫操作)的唯一調(diào)度和處理者匪凉,保證集群事務(wù)處理的順序性枪眉;

      • 集群內(nèi)部各個服務(wù)器的調(diào)度者。

      • 對于 create再层、setData贸铜、delete 等有寫操作的請求堡纬,則需要統(tǒng)一轉(zhuǎn)發(fā)給 leader 處理,leader 需要決定編號蒿秦、執(zhí)行操作烤镐,這個過程稱為一個事務(wù)。

    • Follower

      • 處理客戶端非事務(wù)(即讀操作)請求棍鳖,轉(zhuǎn)發(fā)事務(wù)請求給 Leader炮叶;

      • 參與集群 Leader 選舉投票。

      • 此外渡处,針對訪問量比較大的 zookeeper 集群镜悉,還可新增觀察者角色。

    • Observer:

      • 觀察者角色骂蓖,觀察 Zookeeper 集群的最新狀態(tài)變化并將這些狀態(tài)同步過來积瞒,其對于非事務(wù)請求可以進行獨立處理;對于事務(wù)請求登下,則會轉(zhuǎn)發(fā)給 Leader 服務(wù)器進行處理。

      • 不會參與任何形式的投票只提供非事務(wù)服務(wù)叮喳,通常用于在不影響集群事務(wù)處理能力的前提下提升集群的非事務(wù)處理能力被芳。

  4. Zookeeper 集群搭建

    • Zookeeper 集群搭建指的是 Zookeeper 分布式模式安裝。通常由 2n+1 臺 server 組成馍悟。這是因為為了保證 Leader 選舉(基于Paxos 算法的實現(xiàn))能夠得到多數(shù)的支持畔濒,所以 Zookeeper 集群的數(shù)量一般為奇數(shù)。

    • Zookeeper 運行需要 java 環(huán)境锣咒,所以需要提前安裝 jdk侵状。對于安裝 leader + follower 模式的集群,大致過程如下:

      • 配置主機名稱到 IP 地址映射配置毅整;

      • 修改 Zookeeper 配置文件趣兄;

      • 遠(yuǎn)程復(fù)制分發(fā)安裝文件;

      • 設(shè)置 myid

      • 啟動 Zookeeper 集群悼嫉;

    • 如果要想使用 Observer 模式艇潭,可在對應(yīng)節(jié)點的配置文件(zookeeper-3.4.6/conf/zoo.cfg)添加如下配置:

      • peerType=observer

      其次,必須在配置文件指定哪些節(jié)點被指定為 Observer戏蔑,如:server.1:localhost:2181:3181:observer

    • 這里蹋凝,我們安裝的是 leader + follower 模式

      服務(wù)器IP 主機名 myid
      192.168.88.161 node1 1
      192.168.88.162 node2 2
      192.168.88.163 node3 3
      • 第一步:下載 zookeeper 的壓縮包,官方下載網(wǎng)址如下:http://archive.apache.org/dist/zookeeper/

        我們在這個網(wǎng)址下載我們使用的 zk 版本為 3.4.6

        下載完成之后总棵,上傳到我們的 linux 服務(wù)器的 /export/software 路徑下準(zhǔn)備進行安裝

      • 第二步:解壓

        在 node1 主機上鳍寂,解壓 zookeeper 的壓縮包到 /export/server 路徑下去,然后準(zhǔn)備進行安裝

        cd /export/software
        tar -zxvf zookeeper-3.4.6.tar.gz -C /export/server/
        
      • 第三步:修改配置文件

        在 node1 主機上情龄,修改配置文件

        cd /export/server/zookeeper-3.4.6/conf/
        cp zoo_sample.cfg zoo.cfg
        mkdir -p /export/server/zookeeper-3.4.6/zkdatas/
        vim  zoo.cfg
        

        修改以下內(nèi)容:

        #Zookeeper的數(shù)據(jù)存放目錄
        dataDir=/export/server/zookeeper-3.4.6/zkdatas
        #保留多少個快照      
        autopurge.snapRetainCount=3
        #日志多少小時清理一次
        autopurge.purgeInterval=1
        # 集群中服務(wù)器地址
        server.1=node1:2888:3888
        server.2=node2:2888:3888
        server.3=node3:2888:3888
        
      • 第四步:添加 myid 配置

        在 node1 主機的 /export/server/zookeeper-3.4.6/zkdatas/ 這個路徑下創(chuàng)建一個文件迄汛,文件名為 myid候味,文件內(nèi)容為1

        echo 1 > /export/server/zookeeper-3.4.6/zkdatas/myid 
        
      • 第五步:安裝包分發(fā)并修改 myid 的值

        在 node1 主機上,將安裝包分發(fā)到其他機器

        第一臺機器上面執(zhí)行以下兩個命令

        scp -r  /export/server/zookeeper-3.4.6/ node2:/export/server/
        scp -r  /export/server/zookeeper-3.4.6/ node3:/export/server/
        

        第二臺機器上修改 myid 的值為 2

        echo 2 > /export/server/zookeeper-3.4.6/zkdatas/myid
        

        第三臺機器上修改 myid 的值為 3

        echo 3 > /export/server/zookeeper-3.4.6/zkdatas/myid
        
      • 第六步:配置環(huán)境變量

        分別在三臺機器中隔心,修改 /etc/profile白群,添加以下內(nèi)容:

        export ZOOKEEPER_HOME=/export/server/zookeeper-3.4.6
        export PATH=:$ZOOKEEPER_HOME/bin:$PATH
        

        分別在三臺機器中,source /etc/profile

      • 第七步:三臺機器啟動 zookeeper 服務(wù)

        三臺機器分別啟動 zookeeper 服務(wù)

        這個命令三臺機器都要執(zhí)行

        /export/server/zookeeper-3.4.6/bin/zkServer.sh start
        

        三臺主機分別查看啟動狀態(tài)

        /export/server/zookeeper-3.4.6/bin/zkServer.sh status
        
  5. Zookeeper 數(shù)據(jù)模型

    Zookeeper 的數(shù)據(jù)模型硬霍,在結(jié)構(gòu)上和標(biāo)準(zhǔn)文件系統(tǒng)的非常相似帜慢,擁有一個層次的命名空間,都是采用樹形層次結(jié)構(gòu)唯卖,Zookeeper 樹中的每個節(jié)點被稱為 Znode粱玲。和文件系統(tǒng)的目錄樹一樣,Zookeeper 樹中的每個節(jié)點可以擁有子點點拜轨。但也有不同之處:

    • Znode 兼具文件和目錄兩種特點抽减,既像文件一樣維護著數(shù)據(jù)、元信息橄碾、ACL(訪問控制列表)卵沉、時間戳等數(shù)據(jù)結(jié)構(gòu),又像目錄一樣可以作為路徑標(biāo)識的一部分法牲,并可以具有子 Znode史汗。用戶對 Znode 具有增、刪拒垃、改停撞、查等操作(權(quán)限允許的情況下)。

    • Znode 具有原子性操作悼瓮,讀操作將獲取與節(jié)點相關(guān)的所有數(shù)據(jù)戈毒,寫操作也將替換掉節(jié)點的所有數(shù)據(jù)。另外横堡,每一個節(jié)點都擁有自己的 ACL(訪問控制列表)埋市,這個列表規(guī)定了用戶的權(quán)限,即限定了特定用戶對目標(biāo)節(jié)點可以執(zhí)行的操作翅萤。

    • Znode 存儲數(shù)據(jù)大小有限制恐疲,Znode 雖然可以關(guān)聯(lián)一些數(shù)據(jù),但并沒有被設(shè)計為常規(guī)的數(shù)據(jù)庫或者大數(shù)據(jù)存儲套么,相反的是培己,它用來管理調(diào)度數(shù)據(jù),比如分布式應(yīng)用中的配置文件信息胚泌,狀態(tài)信息省咨、匯集位置等等。這些數(shù)據(jù)的共同特性就是它們都是很小的數(shù)據(jù)玷室,通常以 KB 為大小單位零蓉。Zookeeper 的服務(wù)器和客戶端都被設(shè)計為嚴(yán)格檢查并限制每個 Znode 的數(shù)據(jù)大小至多1M笤受,當(dāng)然常規(guī)使用中應(yīng)該遠(yuǎn)小于此值。

    • Znode 通過路徑引用敌蜂,如同 Unix 中的文件路徑箩兽。路徑必須是絕對的,因此他們必須由斜杠字符來開頭章喉。除此以外汗贫,他們必須是唯一的。也就是說秸脱,每一個路徑只有一個表示落包,因此這些路徑不能改變。在 Zookeeper 中摊唇,路徑由 Unicode 字符串組成咐蝇,并且有一些限制。字符串'/zookeeper'用以保存管理信息巷查,比如關(guān)鍵配額信息有序。

      • stat : 此為狀態(tài)信息,描述該 Znode 的版本吮便,權(quán)限等信息笔呀;

      • data :與該 Znode 關(guān)聯(lián)的數(shù)據(jù)

      • children :該 Znode 下的子節(jié)點

  6. Zookeeper 節(jié)點類型

    Znode 有兩種,分別為臨時節(jié)點永久節(jié)點髓需。

    • 節(jié)點的類型在創(chuàng)建時即被確定,并且不能改變房蝉。

    • 臨時節(jié)點:該節(jié)點的生命周期依賴于它們的會話僚匆。一旦會話結(jié)束,臨時節(jié)點將被自動刪除搭幻,當(dāng)然也可以手動刪除咧擂。臨時節(jié)點不允許擁有子節(jié)點

    • 永久節(jié)點:該節(jié)點的生命周期不依賴會話,并且只有在客戶端顯示執(zhí)行刪除操作的時候檀蹋,他們才能被刪除松申。

    Znode 還有一個序列化的特性,如果創(chuàng)建的時候指定的話俯逾,該 Znode 的名字后面會自動追加一個不斷增加的序列號贸桶。序列號對于此節(jié)點的父節(jié)點來說是唯一的,這樣便于記錄每個子節(jié)點創(chuàng)建的先后順序桌肴。它的格式為"%10d"(10位數(shù)字皇筛,沒有數(shù)值的數(shù)位用0補充,例如“0000000001”)坠七。

    這樣水醋,便會存在四種類型的 Znode 節(jié)點旗笔,分別對應(yīng):

    PERSISTENT:永久節(jié)點;

    EPHEMERAL:臨時節(jié)點拄踪;

    PERSISTENT_SEQUENTIAL:永久節(jié)點蝇恶,序列化(順序)

    EPHEMERAL_SEQUENTIAL:臨時節(jié)點,序列化(順序)

  7. Zookeeper 的 shell 操作

    • 客戶端連接

      運行 zkCli.sh -server ip 進入命令行工具惶桐。

      zkCli.sh -server node1:2181
      
    • 操作命令

      命令 說明 參數(shù)
      create [-s] [-e] path data [acl] 創(chuàng)建 Znode -s 指定是順序節(jié)點撮弧;-e 指定臨時節(jié)點
      ls path [watch] 列出 Path 下所有子 Znode
      get path [watch] 獲取 Path 對應(yīng)的 Znode 的數(shù)據(jù)和屬性
      ls2 path [watch] 查看 Path 下所有子 Znode 以及子 Znode 的屬性
      set path data [version] 更新節(jié)點 version 數(shù)據(jù)版本
      delete path [version] 刪除節(jié)點,如果要刪除的節(jié)點有子 Znode 則無法刪除 version 數(shù)據(jù)版本
      rmr path 刪除節(jié)點耀盗,如果有子 Znode 則遞歸刪除
      setquota -n -b val path 修改 Znode 配置 -n 設(shè)置子節(jié)點最大個數(shù) -b 數(shù)據(jù)最大長度
      history 列出歷史記錄
    • 操作實例

      • 創(chuàng)建普通永久節(jié)點

        create /app1 hello
        

        輸出結(jié)果如下:

        Created /app1

      • 創(chuàng)建永久順序節(jié)點

        create -s /app2 world
        

        輸出結(jié)果如下:

        Created /app20000000001

      • 創(chuàng)建臨時節(jié)點

        create -e /tempnode world
        

        輸出結(jié)果如下:

        Created /tempnode

      • 創(chuàng)建順序的臨時節(jié)點

        create -s -e /tempnode2 aaa
        

        輸出結(jié)果如下:

        Created /tempnode20000000003

      • 獲取節(jié)點數(shù)據(jù)

        get /app1
        

        輸出結(jié)果如下:

        hello
        cZxid = 0x100000002
        ctime = Mon Apr 24 05:11:24 EDT 2023
        mZxid = 0x100000002
        mtime = Mon Apr 24 05:11:24 EDT 2023
        pZxid = 0x100000002
        cversion = 0
        dataVersion = 0
        aclVersion = 0
        ephemeralOwner = 0x0
        dataLength = 5
        numChildren = 0

      • 修改節(jié)點數(shù)據(jù)

        set /app1 hadoop
        

        輸出結(jié)果如下:

        cZxid = 0x100000002
        ctime = Mon Apr 24 05:11:24 EDT 2023
        mZxid = 0x100000006
        mtime = Mon Apr 24 05:14:42 EDT 2023
        pZxid = 0x100000002
        cversion = 0
        dataVersion = 1
        aclVersion = 0
        ephemeralOwner = 0x0
        dataLength = 6
        numChildren = 0

      • 刪除節(jié)點

        delete /app1 #刪除的節(jié)點不能有子節(jié)點
        rmr /app1
        
    • 節(jié)點屬性

      每個 Znode 都包含了一系列的屬性想虎,通過命令 get,可以獲得節(jié)點的屬性叛拷。

      如:

      hello
      cZxid = 0x100000002
      ctime = Mon Apr 24 05:11:24 EDT 2023
      mZxid = 0x100000002
      mtime = Mon Apr 24 05:11:24 EDT 2023
      pZxid = 0x100000002
      cversion = 0
      dataVersion = 0
      aclVersion = 0
      ephemeralOwner = 0x0
      dataLength = 5
      numChildren = 0
      
      • dataVersion:數(shù)據(jù)版本號舌厨,每次對節(jié)點進行 set 操作,dataVersion 的值都會增加1(即使設(shè)置的是相同數(shù)據(jù))忿薇,可有效避免了數(shù)據(jù)更新時出現(xiàn)的先后順序問題裙椭。

      • cversion:子節(jié)點的版本號。當(dāng) Znode 的子節(jié)點有變化時署浩,cversion 的值就會增加1.

      • cZxid:Znode 創(chuàng)建的事務(wù) id揉燃。

      • mZxid:Znode 被修改的事務(wù) id,即每次對 Znode 的修改都會更新 mZxid筋栋。

        對于 zk 來說炊汤,每次的變化都會產(chǎn)生一個唯一的事務(wù)id,zxid(Zookeeper Transaction id)弊攘。通過 zxid抢腐,可以確定更新操作的先后順序。例如襟交,如果 zxid1 小于 zxid2迈倍,說明 zxid1 操作先于 zxid2 發(fā)生。zxid 對于整個 zk 都是唯一的捣域,即使操作的是不同的 znode啼染。

      • ctime:節(jié)點創(chuàng)建時的時間戳;

      • mtime:節(jié)點最新一次更新發(fā)生時的時間戳焕梅;

      • ephemralOwner:如果該節(jié)點為臨時節(jié)點迹鹅,ephemeralOwner 的值表示與該節(jié)點綁定的 session id。如果不是丘侠,ephemeralOwner 的值為0徒欣;

        在 client 和 server 通信之前,首先需要建立連接蜗字,該連接稱為 session打肝。連接建立后脂新,如果發(fā)生連接超時、授權(quán)失敗粗梭,或者顯式關(guān)閉連接争便,連接便處理 Closed 狀態(tài),此時 session 結(jié)束断医。

  8. Zookeeper Watch(監(jiān)聽機制)

    Zookeeper 提供了分布式數(shù)據(jù)發(fā)布/訂閱功能滞乙,一個典型的發(fā)布/訂閱模型系統(tǒng)定義了一種一對多的訂閱關(guān)系,能讓多個訂閱者同時監(jiān)聽某一個主題對象鉴嗤。當(dāng)這個主題對象自身狀態(tài)變化時斩启,會通知所有訂閱者,使他們能夠做出相應(yīng)的處理醉锅。

    Zookeeper 中兔簇,引入了 Watcher 機制來實現(xiàn)這種分布式的通知功能。Zookeeper 允許客戶端向服務(wù)器注冊一個 Watcher 監(jiān)聽硬耍。當(dāng)服務(wù)端的一些事件觸發(fā)了這個 Watcher垄琐,那么就會向指定客戶端發(fā)送一個事件通知來實現(xiàn)分布式通知功能。

    觸發(fā)事件種類很多经柴,如:節(jié)點創(chuàng)建狸窘、節(jié)點刪除、節(jié)點改變坯认、子節(jié)點改變等翻擒。

    總的來說可以概括 Watcher 為以下三個過程:客戶端向服務(wù)器注冊 Watcher、服務(wù)端事件發(fā)生觸發(fā)Watcher牛哺、客戶端回調(diào) Watcher 得到觸發(fā)事件情況韭寸。

    • Watch 機制特點

      • 一次性觸發(fā)

        事件發(fā)生觸發(fā)監(jiān)聽,一個 watcher event 就會被發(fā)送到設(shè)置監(jiān)聽的客戶端荆隘,這種效果是一次性的,后續(xù)再次發(fā)生同樣的事件赴背,不會再次觸發(fā)椰拒。

      • 事件封裝

        Zookeeper 使用 WatchedEvent 對象來封裝服務(wù)端事件并傳遞。

        WatchedEvent 包含了每一個事件的三個基本屬性:通知狀態(tài)(keeperState)凰荚、事件類型(EventType) 和節(jié)點路徑(path)

      • event 異步發(fā)送

        watcher 的通知事件從服務(wù)端發(fā)送到客戶端是異步的燃观。

      • 先注冊再觸發(fā)

        Zookeeper 中的 watch機制,必須客戶端先去服務(wù)端注冊監(jiān)聽便瑟,這樣事件發(fā)送才會觸發(fā)監(jiān)聽缆毁,通知客戶端

    • 通知狀態(tài)和事件類型

      同一個事件類型在不同的通知狀態(tài)中代表的含義有所不同,下有列舉了常見的通知狀態(tài)和事件類型到涂。

      事件封裝:Wather 得到的事件是被封裝過的脊框,包括三個內(nèi)容:keeperState颁督、eventType、path

      KeeperState EventType 觸發(fā)條件 說明
      None 連接成功
      SyncConnected NodeCreated Znode 被創(chuàng)建 此時處于連接狀態(tài)
      SyncConnected NodeDeleted Znode 被刪除 此時處于連接狀態(tài)
      SyncConnected NodeDataChanged Znode 數(shù)據(jù)被改變 此時處于連接狀態(tài)
      SyncConnected NodeChildChanged Znode 的子Znode 數(shù)據(jù)被改變 此時處于連接狀態(tài)
      Disconnected None 客戶端和服務(wù)器端斷開連接 客戶端和服務(wù)器處于斷開連接狀態(tài)
      Expired None 會話超時 會收到一個 SessionExpired
      AuthFail None 權(quán)限驗證失敗 會收到一個 AuthFailedException

      其中連接狀態(tài)事件(type=None,path=null)不需要客戶端注冊浇雹,客戶端只要有需要直接處理就行了沉御。

  9. Shell 客戶端設(shè)置 watcher

    • 設(shè)置節(jié)點數(shù)據(jù)變動監(jiān)聽

      [zk: node1:2181(CONNECTED) 14] get /app10000000005 watch
      

      輸出結(jié)果如下:

      hello
      cZxid = 0x10000000a
      ctime = Mon Apr 24 05:52:33 EDT 2023
      mZxid = 0x10000000a
      mtime = Mon Apr 24 05:52:33 EDT 2023
      pZxid = 0x10000000a
      cversion = 0
      dataVersion = 0
      aclVersion = 0
      ephemeralOwner = 0x0
      dataLength = 5
      numChildren = 0

    • 通過另一個客戶端更改節(jié)點數(shù)據(jù)

      [zk: node1:2181(CONNECTED) 15] set /app10000000005 hello22
      

      輸出結(jié)果如下:

      WATCHER::cZxid = 0x10000000a
      WatchedEvent state:SyncConnected type:NodeDataChanged path:/app10000000005
      ctime = Mon Apr 24 05:52:33 EDT 2023
      mZxid = 0x10000000b
      mtime = Mon Apr 24 05:53:48 EDT 2023
      pZxid = 0x10000000a
      cversion = 0
      dataVersion = 1
      aclVersion = 0
      ephemeralOwner = 0x0
      dataLength = 7
      numChildren = 0

      此時設(shè)置監(jiān)聽的節(jié)點收到通知

  10. Zookeeper Java API 操作

     這里操作 Zookeeper 的 JavaAPI 使用的是一套 Zookeeper 框架 Curator,解決了很多 Zookeeper 客戶端非常底層的細(xì)節(jié)開發(fā)工作昭灵。
    

    Curator 包含了幾個包:

    • curator-framework:對 zookeeper 的底層 api 的一些封裝
    • curator-recipes:封裝了一些高級特性吠裆,如:Cache 事件監(jiān)聽、選舉烂完、分布式鎖试疙、分布式計數(shù)器等

    Maven 依賴(使用 curator 版本:2.12.0,對應(yīng) Zookeeper 的版本為:3.4.x抠蚣,如果跨版本會有兼容性問題祝旷,很有可能會導(dǎo)致節(jié)點操作失敗)

    • 引入 Maven 依賴:

      <dependencies>
              <dependency>
                  <groupId>org.apache.curator</groupId>
                  <artifactId>curator-framework</artifactId>
                  <version>2.12.0</version>
              </dependency>
      
              <dependency>
                  <groupId>org.apache.curator</groupId>
                  <artifactId>curator-recipes</artifactId>
                  <version>2.12.0</version>
              </dependency>
      
              <dependency>
                  <groupId>com.google.collections</groupId>
                  <artifactId>google-collections</artifactId>
                  <version>1.0</version>
              </dependency>
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>RELEASE</version>
              </dependency>
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-simple</artifactId>
                  <version>1.7.25</version>
              </dependency>
          </dependencies>
      
          <build>
              <plugins>
                  <!-- java編譯插件 -->
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <version>3.2</version>
                      <configuration>
                          <source>1.8</source>
                          <target>1.8</target>
                          <encoding>UTF-8</encoding>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      
    • 節(jié)點操作

      • ZnodeOperator.java 文件的代碼如下:

        package Znode;
        
        import org.apache.curator.RetryPolicy;
        import org.apache.curator.framework.CuratorFramework;
        import org.apache.curator.framework.CuratorFrameworkFactory;
        import org.apache.curator.retry.ExponentialBackoffRetry;
        import org.apache.zookeeper.CreateMode;
        
        public class ZnodeOperator {
            public void createZnode() throws Exception {
                //1. 定制一個重試策略
                /**
                 * param1:重試的間隔時間
                 * param2:重試的最大次數(shù)
                 */
                RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1);
                //2. 獲取一個客戶端對象
                /**
                 * param1:要連接的 Zookeeper 服務(wù)器列表
                 * param2:會話的超時時間
                 * param3:鏈接超時時間
                 * param4:重試策略
                 */
                String connectionStr = "192.168.88.161:2181,192.168.88.162:2181,192.168.88.163:2181";
                CuratorFramework client = CuratorFrameworkFactory.newClient(connectionStr,8000,8000,retryPolicy);
                //3.開戶客戶端
                client.start();
                //4.創(chuàng)建節(jié)點
                /**
                 * 節(jié)點類型:
                 * CreateMode.PERSISTANT:永久節(jié)點
                 * CreateMode.PERSISTANT_SEQUENTIAL:永久序列化節(jié)點
                 * CreateMode.EPHEMERAL:臨時節(jié)點
                 * CreateMode.EPHEMERAL_SEQUENTIAL:臨時序列化節(jié)點
                 */
                client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello3","world".getBytes());
                //5.關(guān)閉客戶端
                client.close();
            }
        }
        
      • Test.java 測試類的代碼如下:

        package Znode;
        
        public class Test {
            public static void main(String[] args) throws Exception {
                ZnodeOperator operator = new ZnodeOperator();
                operator.createZnode();
            }
        }
        
      • 輸出結(jié)果如下:

        ......
        [main-SendThread(192.168.88.163:2181)] INFO org.apache.zookeeper.ClientCnxn - Socket connection established to 192.168.88.163/192.168.88.163:2181, initiating session
        [main-SendThread(192.168.88.163:2181)] INFO org.apache.zookeeper.ClientCnxn - Session establishment complete on server 192.168.88.163/192.168.88.163:2181, sessionid = 0x387b220a2240000, negotiated timeout = 8000
        [main-EventThread] INFO org.apache.curator.framework.state.ConnectionStateManager - State change: CONNECTED
        [Curator-Framework-0] INFO org.apache.curator.framework.imps.CuratorFrameworkImpl - backgroundOperationsLoop exiting
        [main] INFO org.apache.zookeeper.ZooKeeper - Session: 0x387b220a2240000 closed

        Process finished with exit code 0

      • 我們再通過 Zookeeper 的 shell 操作, 在 Linux 上 shell 窗口上通過 ls path 的方式郑原,能成功驗證 znode 確實已經(jīng)被我們創(chuàng)建成功蛀序。如下所示:

        WatchedEvent state:SyncConnected type:None path:null
        [zk: node1:2181(CONNECTED) 0] ls /hello2
        []
        
  11. Zookeeper 選舉機制

    Zookeeper 默認(rèn)的算法是 FastLeaderElection,采用投票數(shù)大于半數(shù)則勝出的邏輯

    • 概念

      • 服務(wù)器ID

        比如有三臺服務(wù)器敌完,編號分別為1,2,3

        編號越大,在選擇算法中的權(quán)重越大

      • 選舉狀態(tài)

        LOOKING羊初,競選狀態(tài)滨溉;

        FOLLOWING,隨從狀態(tài)长赞,同步 leader 狀態(tài)晦攒,參與投票。

        OBSERVING, 觀察狀態(tài)得哆,同步 leader 狀態(tài)脯颜,不參與投票。

        LEADING贩据,領(lǐng)導(dǎo)者狀態(tài)栋操。

      • 數(shù)據(jù) ID

        服務(wù)器中存放的最新數(shù)據(jù) version。

        值越大說明數(shù)據(jù)越新饱亮,在選舉算法中數(shù)據(jù)越新權(quán)重越大矾芙。

      • 邏輯時鐘

        也叫投票的次數(shù),同一輪投票過程中的邏輯時鐘值是相同的近上。每投完一次票這個數(shù)據(jù)就會增加剔宪,然后與接收到的其它服務(wù)器返回的投票信息中的數(shù)值相比,根據(jù)不同的值做出不同的判斷。

    • 全新集群選舉

      假設(shè)目前有5臺服務(wù)器葱绒,每臺服務(wù)器均沒有數(shù)據(jù)感帅,它們的編號分別是1、2哈街、3留瞳、4、5骚秦,按編號依次啟動她倘,它們的選舉過程如下:

      • 服務(wù)器1啟動,給自己投票作箍,然后發(fā)投票信息硬梁。由于其它機器還沒有啟動,所以它收不到反饋信息胞得,服務(wù)器1的狀態(tài)一直屬于 Looking荧止。
      • 服務(wù)器2啟動,給自己投票阶剑,同時與之前啟動的服務(wù)器1交換結(jié)果跃巡。由于服務(wù)器2的編號大,所以服務(wù)器2勝出牧愁。但此時投票數(shù)沒有大于半數(shù)素邪,所以兩個服務(wù)器的狀態(tài)依然是 Looking。
      • 服務(wù)器3啟動猪半,給自己投票兔朦,同時與之前啟動的服務(wù)器1、2交換結(jié)果磨确。由于服務(wù)器3的編號最大沽甥,所以服務(wù)器3勝出。此時投票數(shù)正好大于半數(shù)乏奥,所以服務(wù)器3成為領(lǐng)導(dǎo)者摆舟,服務(wù)器1、2 成為小弟邓了。
      • 服務(wù)器4啟動盏檐,給自己投票,同時與之前啟動的服務(wù)器1驶悟、2、3交換信息材失,盡管服務(wù)器4的編號大痕鳍,但之前的服務(wù)器3已經(jīng)勝出,所以服務(wù)器4只能成為小弟。
      • 服務(wù)器5啟動笼呆,后面的邏輯同服務(wù)器4成為小弟熊响。
    • 非全新集群選舉

      對于運行正常的 Zookeeper 集群,中途有機器down 掉诗赌,需要重新選舉時汗茄,選舉過程就需要加入數(shù)據(jù)ID、服務(wù)器ID 和邏輯時鐘铭若。

      數(shù)據(jù)ID:數(shù)據(jù)新的 version 就大,數(shù)據(jù)每次更新都會更新 version 。

      服務(wù)器 ID:就是我們配置的 myid 中的值嫂侍,每個機器一個颓影。

      邏輯時鐘:這個值從0開始遞增揪阿,每次選舉對應(yīng)一個值。如果在同一次選舉中溺健,這個值是一致的魏颓。

      這樣選舉的標(biāo)準(zhǔn)就變成:

      • 邏輯時鐘小的選舉結(jié)果被忽略沦童,重新投票墩瞳;
      • 統(tǒng)一邏輯時鐘后,數(shù)據(jù) id 大的勝出;
      • 數(shù)據(jù) id 相同的情況下,服務(wù)器 id 大的勝出和蚪。

      根據(jù)這個規(guī)則選出 Leader。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伏社,一起剝皮案震驚了整個濱河市速妖,隨后出現(xiàn)的幾起案子稿饰,更是在濱河造成了極大的恐慌喉镰,老刑警劉巖脖咐,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件产弹,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機悬垃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門廊佩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靖榕,“玉大人标锄,你說我怎么就攤上這事⌒蚓兀” “怎么了鸯绿?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長簸淀。 經(jīng)常有香客問我瓶蝴,道長,這世上最難降的妖魔是什么租幕? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任舷手,我火速辦了婚禮,結(jié)果婚禮上劲绪,老公的妹妹穿的比我還像新娘男窟。我一直安慰自己盆赤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布歉眷。 她就那樣靜靜地躺著牺六,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汗捡。 梳的紋絲不亂的頭發(fā)上淑际,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音扇住,去河邊找鬼春缕。 笑死,一個胖子當(dāng)著我的面吹牛艘蹋,可吹牛的內(nèi)容都是我干的锄贼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼女阀,長吁一口氣:“原來是場噩夢啊……” “哼宅荤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起强品,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤膘侮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后的榛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琼了,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年夫晌,在試婚紗的時候發(fā)現(xiàn)自己被綠了雕薪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡晓淀,死狀恐怖所袁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凶掰,我是刑警寧澤燥爷,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站懦窘,受9級特大地震影響前翎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畅涂,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一港华、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧午衰,春花似錦立宜、人聲如沸冒萄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尊流。三九已至,卻和暖如春灯帮,著一層夾襖步出監(jiān)牢的瞬間奠旺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工施流, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鄙信。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓瞪醋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親装诡。 傳聞我的和親對象是個殘疾皇子银受,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容