zookeeper介紹和簡單入門

1. zookeeper概述

Zookeeper 是一個開源的分佈式協調服務框架 ,主要用來解決分佈式集羣中應用系統的一致性問題和數據管理問題

在這裏插入圖片描述

Zookeeper 本質上是一個分佈式文件系統, 適合存放小文件,也可以理解爲一個數據庫

1.1 zookeeper集羣

Zookeeper集羣是一個基於主從架構高可用

在這裏插入圖片描述

  • Leader 一個Zookeeper集羣同一時間只會有一個實際工作的Leader,它會發起並維護與各Follwer及Observer間的心跳。所有的寫操作必須要通過Leader完成再由Leader將寫操作廣播給其它服務器。
  • Follower 一個Zookeeper集羣可能同時存在多個Follower,它會響應Leader的心跳。Follower可直接處理並返回客戶端的讀請求,同時會將寫請求轉發給Leader處理,並且負責在Leader處理寫請求時對請求進行投票。
  • Observer 角色與Follower類似,但是無投票權

1.2 zookeeper數據模型

ZooKeeper 的數據模型,在結構上和標準文件系統的非常相似,擁有一個層次的命名空間,都是採用樹形層次結構.
在這裏插入圖片描述
在這裏插入圖片描述

ZooKeeper 樹中的每個節點被稱爲—個Znode。和文件系統的目錄樹一樣,ZooKeeper 樹中的每個節點可以擁有子節點,

  • Znode既具備文件的特性又具有文件夾的特性。
    • Znode 是有路徑的, 例如 /data/host1, /data/host2, 這個路徑也可以理解爲是 Znode 的 Name
    • Znode 也可以攜帶數據, 例如說某個 Znode 的路徑是 /data/host1, 其值是一個字符串 "192.168.0.1"
  • Znode 存儲數據大小有限制,ZooKeeper用來管理調度數據,每個 Znode 的數據大小至多 1M,常規使用中應該遠小於此值。
  • Znode 通過路徑引用路徑必須是絕對且唯一的,因此他們必須由斜槓字符來開頭,每一個路徑只有一個表示,不能改變。在 ZooKeeper 中,路徑由 Unicode 字符串組成,並且有一些限制。字符串"/zookeeper"用以保存管理 信息,比如關鍵配額信息
  • 每個 Znode 由 3 部分組成:
    • state:此爲狀態信息, 描述該 Znode 的版本, 權限等信息
    • data:與該 Znode 關聯的數據
    • children:該 Znode 下的子節點

1.3 Znode節點類型

每個Znode有兩大特性, 可以構成四種不同類型的Znode

  • 持久性
    • 持久 :客戶端斷開時, 不會刪除持有的Znode,並且只有在客戶端顯示執行刪除操作的時候,才能被刪除。
    • 臨時:客戶端斷開時, 刪除所有持有的Znode, 臨時Znode不允許有子Znode,該節點的生命週期依賴於創建它們的會話。一旦會話結束,臨時節點將被自動刪除,也可以手動刪除。臨時節點不允許擁有子節點。可以結合watch機制判斷主機的存活狀態
  • 順序性
    • 有序 :創建的Znode有先後順序, 順序就是在後面追加一個序列號, 序列號是由父節點管理的自增,如果創建的時候指定的話,該 Znode 的名字後面會自動追加一個不斷增加的序列號。序列號對於此節點的父節點來說是唯一的,這樣便會記錄每個子節點創建的先後順序。它的格式爲“%10d”(10 位數字,沒有數值的數位用 0 補充,例如“0000000001”)。
    • 無序: 創建的Znode沒有先後順序

2. Zookeeper的watch機制

watch機制可以監聽Znode結點的變化,當Znode發生變化的時候, WatchManager會調用對應的Watcher,當Znode發生刪除, 修改, 創建, 子節點修改的時候, 對應的Watcher會得到通知

  • watch機制可以進行發佈和訂閱

    在這裏插入圖片描述

  • watch機制可以監控集羣中主機的存活狀態

    在這裏插入圖片描述

    ​ node01宕機後,臨時節點消失,node02代替node01

    在這裏插入圖片描述

Watcher的特點

  • 一次性觸發 一個 Watcher 只會被觸發一次, 如果需要繼續監聽, 則需要再次添加 Watcher
  • 事件封裝: Watcher 得到的事件是被封裝過的, 包括三個內容 keeperState(狀態), eventType(類型), path(路徑)

3. Zookeeper的選舉機制

Leader選舉是保證分佈式數據一致性的關鍵所在。當Zookeeper集羣中的一臺服務器出現以下兩種情況之一時,需要進入Leader選舉。

  • 服務器啓動時期的Leader選舉

    若進行Leader選舉,則至少需要兩臺機器,這裏選取3臺機器組成的服務器集羣爲例。在集羣初始化階段,當有一臺服務器Server1啓動時,其單獨無法進行和完成Leader選舉,當第二臺服務器Server2啓動時,此時兩臺機器可以相互通信,每臺機器都試圖找到Leader,於是進入Leader選舉過程。選舉過程如下

    (1) 每個Server發出一個投票。由於是初始情況,Server1和Server2都會將自己作爲Leader服務器來進行投票,每次投票會包含所推舉的服務器的myid和ZXID(myid:服務器的唯一標識,權值,越大說明服務器越好;zxid:事務id,值越大表示事物越新),使用(myid, ZXID)來表示,此時Server1的投票爲(1, 0),Server2的投票爲(2, 0),然後各自將這個投票發給集羣中其他機器。

    (2) 接受來自各個服務器的投票。集羣的每個服務器收到投票後,首先判斷該投票的有效性,如檢查是否是本輪投票、是否來自LOOKING狀態的服務器。

    (3) 處理投票。針對每一個投票,服務器都需要將別人的投票和自己的投票進行PK,PK規則如下

    · 優先檢查ZXID。ZXID比較大的服務器優先作爲Leader。

    · 如果ZXID相同,那麼就比較myid。myid較大的服務器作爲Leader服務器。

    對於Server1而言,它的投票是(1, 0),接收Server2的投票爲(2, 0),首先會比較兩者的ZXID,均爲0,再比較myid,此時Server2的myid最大,於是更新自己的投票爲(2, 0),然後重新投票,對於Server2而言,其無須更新自己的投票,只是再次向集羣中所有機器發出上一次投票信息即可。

    (4) 統計投票。每次投票後,服務器都會統計投票信息,判斷是否已經有過半機器接受到相同的投票信息,對於Server1、Server2而言,都統計出集羣中已經有兩臺機器接受了(2, 0)的投票信息,此時便認爲已經選出了Leader。

    (5) 改變服務器狀態。一旦確定了Leader,每個服務器就會更新自己的狀態,如果是Follower,那麼就變更爲FOLLOWING,如果是Leader,就變更爲LEADING。

  • 服務器運行時期的Leader選舉

    在Zookeeper運行期間,Leader與非Leader服務器各司其職,即便當有非Leader服務器宕機或新加入,此時也不會影響Leader,但是一旦Leader服務器宕機,那麼整個集羣將暫停對外服務,進入新一輪Leader選舉,其過程和啓動時期的Leader選舉過程基本一致過程相同。

4. Zookeeper的應用場景

4.1 數據發佈/訂閱

數據發佈/訂閱系統,需要發佈者將數據發佈到Zookeeper的節點上,供訂閱者進行數據訂閱,進而達到動態獲取數據的目的,實現配置信息的集中式管理和數據的動態更新。

​ 發佈/訂閱一般有兩種設計模式:推模式拉模式,服務端主動將數據更新發送給所有訂閱的客戶端稱爲推模式;客戶端主動請求獲取最新數據稱爲拉模式.

Zookeeper採用了推拉相結合的模式,客戶端向服務端註冊自己需要關注的節點,一旦該節點數據發生變更,那麼服務端就會向相應的客戶端推送Watcher事件通知,客戶端接收到此通知後,主動到服務端獲取最新的數據

在這裏插入圖片描述

4.2 命名服務

命名服務是分步實現系統中較爲常見的一類場景,分佈式系統中,被命名的實體通常可以是集羣中的機器、提供的服務地址或遠程對象等,通過命名服務,客戶端可以根據指定名字來獲取資源的實體,在分佈式環境中,上層應用僅僅需要一個全局唯一的名字。Zookeeper可以實現一套分佈式全局唯一ID的分配機制。

在這裏插入圖片描述

通過調用Zookeeper節點創建的API接口就可以創建一個順序節點,並且在API返回值中會返回這個節點的完整名字,利用此特性,可以生成全局ID,其步驟如下

  1. 客戶端根據任務類型,在指定類型的任務下通過調用接口創建一個順序節點,如"job-"。
  2. 創建完成後,會返回一個完整的節點名,如"job-00000001"。
  3. 客戶端拼接type類型和返回值後,就可以作爲全局唯一ID了,如"type2-job-00000001"。
4.3 分佈式協調/通知

Zookeeper中特有的Watcher註冊於異步通知機制,能夠很好地實現分佈式環境下不同機器,甚至不同系統之間的協調與通知,從而實現對數據變更的實時處理。通常的做法是不同的客戶端都對Zookeeper上的同一個數據節點進行Watcher註冊,監聽數據節點的變化(包括節點本身和子節點),若數據節點發生變化,那麼所有訂閱的客戶端都能夠接收到相應的Watcher通知,並作出相應處理。

在絕大多數分佈式系統中,系統機器間的通信無外乎心跳檢測工作進度彙報系統調度

心跳檢測,不同機器間需要檢測到彼此是否在正常運行,可以使用Zookeeper實現機器間的心跳檢測,基於其臨時節點特性(臨時節點的生存週期是客戶端會話,客戶端若當即後,其臨時節點自然不再存在),可以讓不同機器都在Zookeeper的一個指定節點下創建臨時子節點,不同的機器之間可以根據這個臨時子節點來判斷對應的客戶端機器是否存活。通過Zookeeper可以大大減少系統耦合。

工作進度彙報,通常任務被分發到不同機器後,需要實時地將自己的任務執行進度彙報給分發系統,可以在Zookeeper上選擇一個節點,每個任務客戶端都在這個節點下面創建臨時子節點,這樣不僅可以判斷機器是否存活,同時各個機器可以將自己的任務執行進度寫到該臨時節點中去,以便中心繫統能夠實時獲取任務的執行進度。

系統調度,Zookeeper能夠實現如下系統調度模式:分佈式系統由控制檯和一些客戶端系統兩部分構成,控制檯的職責就是需要將一些指令信息發送給所有的客戶端,以控制他們進行相應的業務邏輯,後臺管理人員在控制檯上做一些操作,實際上就是修改Zookeeper上某些節點的數據,Zookeeper可以把數據變更以時間通知的形式發送給訂閱客戶端。

4.4分佈式鎖

分佈式鎖用於控制分佈式系統之間同步訪問共享資源的一種方式,可以保證不同系統訪問一個或一組資源時的一致性,主要分爲排它鎖共享鎖

排它鎖又稱爲寫鎖或獨佔鎖,若事務T1對數據對象O1加上了排它鎖,那麼在整個加鎖期間,只允許事務T1對O1進行讀取和更新操作,其他任何事務都不能再對這個數據對象進行任何類型的操作,直到T1釋放了排它鎖。

在這裏插入圖片描述

獲取鎖,在需要獲取排它鎖時,所有客戶端通過調用接口,在/exclusive_lock節點下創建臨時子節點/exclusive_lock/lock。Zookeeper可以保證只有一個客戶端能夠創建成功,沒有成功的客戶端需要註冊/exclusive_lock節點監聽。

釋放鎖,當獲取鎖的客戶端宕機或者正常完成業務邏輯都會導致臨時節點的刪除,此時,所有在/exclusive_lock節點上註冊監聽的客戶端都會收到通知,可以重新發起分佈式鎖獲取。

共享鎖又稱爲讀鎖,若事務T1對數據對象O1加上共享鎖,那麼當前事務只能對O1進行讀取操作,其他事務也只能對這個數據對象加共享鎖,直到該數據對象上的所有共享鎖都被釋放。在需要獲取共享鎖時,所有客戶端都會到/shared_lock下面創建一個臨時順序節點

在這裏插入圖片描述

4.5 分佈式隊列

有一些時候,多個團隊需要共同完成一個任務,比如,A團隊將Hadoop集羣計算的結果交給B團隊繼續計算,B完成了自己任務再交給C團隊繼續做。這就有點像業務系統的工作流一樣,一環一環地傳下 去.

分佈式環境下,我們同樣需要一個類似單進程隊列的組件,用來實現跨進程跨主機跨網絡數據共享數據傳遞,這就是我們的分佈式隊列。

5. zookeeper客戶端操作

  • 先查看zookeeper服務是否啓動
/export/servers/zookeeper-3.4.9/bin/zkServer.sh status

如果沒啓動,先啓動zookeeper服務

sudo /export/servers/zookeeper-3.4.9/bin/zkServer.sh start
  • 登陸zookeeper客戶端
cd /export/servers/zookeeper-3.4.9/
# 啓動服務器
bin/zkCli.sh  -server hadoop1:2181
# 退出
quit
# 列出path下的所有Znode
ls /

在這裏插入圖片描述

/zookeeper保存管理信息,比如關鍵配額信息等

  • 創建結點
  • 創建永久節點

    # 創建結點hello,寫入內容world
    create /hello world
    
  • 創建臨時節點

    create -e /abc 123
    
  • 創建 永久序列化節點

    create -s /hi java
    
  • 創建臨時序列化節點

    create -s -e /okay fine
    ls /
    

    在這裏插入圖片描述

    quit
    bin/zkCli.sh  -server hadoop1:2181
    ls /
    

    在這裏插入圖片描述

  • 創建子節點

    create /hello/123 aa
    ls /hello
    

    在這裏插入圖片描述

  • 刪除結點

    # 刪除無子節點的Znode
    delete /hi0000000002
    # 刪除有子節點的Znode
    rmr /hello
    ls /
    

    在這裏插入圖片描述

  • 列出歷史記錄

    history
    

    在這裏插入圖片描述

  • 得到節點屬性

    • dataVersion:數據版本號,每次對節點進行 set 操作,dataVersion 的值都會增加 1(即使設置的是相同的數據),可有效避免了數據更新時出現的先後順序問題。
    • cversion:子節點的版本號。當 znode 的子節點有變化時,cversion 的值就會增加 1。
    • aclVersion :ACL 的版本號。
    • cZxid :Znode 創建的事務 id。
    • mZxid :Znode 被修改的事務 id,即每次對 znode 的修改都會更新 mZxid。
    • ctime:節點創建時的時間戳.
    • mtime:節點最新一次更新發生時的時間戳.
    • ephemeralOwner:如果該節點爲臨時節點, ephemeralOwner 值表示與該節點綁定的 session id. 如果不 是,ephemeralOwner 值爲 0.
    get /hello
    

    在這裏插入圖片描述

  • 更改Znode的值

    set /hello zookeeper
    

    在這裏插入圖片描述

命令 說明 參數
create [-s] [-e] path(路徑) data(數據) acl(權限控制) 創建Znode -s 指定是順序節點
-e 指定是臨時節點
ls path [watch] 列出Path下所有子Znode
get path [watch] 獲取Path對應的Znode的數據和屬性
ls2 path [watch] 查看Path下所有子Znode以及子Znode的屬性
set path data [version] 更新節點 version 數據版本
delete path [version] 刪除節點, 如果要刪除的節點有子Znode則無法刪除 version 數據版本
rmr path 刪除節點, 如果有子Znode則遞歸刪除
setquota -n|-b val path 修改Znode配額 -n 設置子節點最大個數
-b 設置節點數據最大長度
history 列出歷史記錄
  • 添加watch機制

    # 先打開一個窗口添加watch
    get /hello watch
    # 然後打開另外一個窗口,更改znode的值
    set /hello java
    

    watch機制會給出追蹤

    在這裏插入圖片描述

    state、type變化的含義:

    KeeperState EventType 觸發條件 說明
    None 連接成功
    SyncConnected NodeCreated Znode被創建 此時處於連接狀態
    SyncConnected NodeDeleted Znode被刪除 此時處於連接狀態
    SyncConnected NodeDataChanged Znode數據被改變 此時處於連接狀態
    SyncConnected NodeChildChanged Znode的子Znode數據被改變 此時處於連接狀態
    Disconnected None 客戶端和服務端斷開連接 此時客戶端和服務器處於斷開連接狀態
    Expired None 會話超時 會收到一個SessionExpiredExceptio
    AuthFailed None 權限驗證失敗 會收到一個AuthFailedException
發佈了87 篇原創文章 · 獲贊 32 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章