溫故知新-快速理解zookeeper功能&應用&選舉機制



zookeeper簡介

什麼是zookeeper

  • zooKeeper由雅虎研究院開發, 是Google Chubby的開源實現, 後來託管到Apache, 於2010年11月正式成爲Apache的頂級項目。
    ​- 大數據生態系統裏的很多組件的命名都是某種動物或者昆蟲, 比如hadoop就是🐘, hive就是🐝。 zookeeper即動物園管理者, 顧名思義就是管理大數據生態系統各組件
    的管理員, 如下圖所示:
    zookeeper

zookeeper應用場景

zooKeeper是一個經典的分佈式數據一致性解決方案, 致力於爲分佈式應用提供一個高性能、 高可用, 且具有嚴格順序訪問控制能力的分佈式協調存儲服務。

  • 維護配置信息
  • 分佈式鎖服務
  • 集羣管理
  • 生成分佈式唯一ID

zookeeper特點

  • 高性能

zooKeeper將全量數據存儲在內存中, 並直接服務於客戶端的所有非事務請求, 尤其適用於以讀爲主的應用場景

  • 高可用

zooKeeper一般以集羣的方式對外提供服務, 一般3 ~ 5臺機器就可以組成一個可用的Zookeeper集羣了, 每臺機器都會在內存中維護當前的服務器狀態, 並且每臺機器之間都相
互保持着通信。 只要集羣中超過一半的機器都能夠正常工作, 那麼整個集羣就能夠正常對外服務

  • 嚴格順序訪問

對於來自客戶端的每個更新請求, ZooKeeper都會分配一個全局唯一的遞增編號,這個編號反映了所有事務操作的先後順序

zookeeper的數據模型

  • zookeeper的數據節點可以視爲樹狀結構(或者目錄) , 樹中的各節點被稱爲znode(即zookeeper node) , 一個znode可以有多個子節點。 zookeeper節點在結構上表現爲樹狀; 使用路徑path來定位某個znode;
  • znode, 兼具文件和目錄兩種特點。 既像文件一樣維護着數據、 元信息、 ACL(權限控制)、 時間戳等數據結構, 又像目錄一樣可以作爲路徑標識的一部分;
    結構

節點數據結構

  • 一個znode大體上分爲3各部分:
    • 節點的數據: 即znode data(節點path, 節點data)的關係就像是java map中(key,value)的關係節點的子節點children
    • 節點的狀態stat: 用來描述當前節點的創建、 修改記錄, 包括cZxid、 ctime等
    • 節點狀態stat的屬性
[zk: localhost:2181(CONNECTED) 7] get /ns-1/tenant
cZxid = 0x6a0000000a
ctime = Wed Mar 27 09:56:44 CST 2019
mZxid = 0x6a0000000a
mtime = Wed Mar 27 09:56:44 CST 2019
pZxid = 0x6a0000000e
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
  • 屬性說明:

    cZxid: 數據節點創建時的事務 ID
    ctime: 數據節點創建時的時間
    mZxid: 數據節點最後一次更新時的事務 ID
    mtime: 數據節點最後一次更新時的時間
    pZxid: 數據節點的子節點最後一次被修改時的事務 ID
    cversion: 子節點的更改次數
    dataVersion: 節點數據的更改次數
    aclVersion: 節點的 ACL 的更改次數
    ephemeralOwner: 如果節點是臨時節點, 則表示創建該節點的會話的
    SessionID; 如果節點是持久節點, 則該屬性值爲 0
    dataLength: 數據內容的長度
    numChildren: 數據節點當前的子節點個數

節點類型

zookeeper中的節點有兩種, 分別爲臨時節點和永久節點。節點的類型在創建時即被確定, 並且不能改變。

  • 臨時節點: 該節點的生命週期依賴於創建它們的會話。 一旦會話(Session)結束, 臨時節點將被自動刪除, 當然可以也可以手動刪除。 雖然每個臨時的Znode都會綁定到一個客戶端會話, 但他們對所有的客戶端還是可見的。 另外, ZooKeeper的臨時節點不允許擁有子節點。
  • 持久化節點: 該節點的生命週期不依賴於會話, 並且只有在客戶端顯示執行刪除操作的時候, 他們才能被刪除;

zookeeper常用Shell命令

  • 新增節點

create [-s] [-e] path data #其中-s 爲有序節點, -e 臨時節點

  • 更新節點

更新節點的命令是 set , 可以直接進行修改eg:set /hadoop “345”
基於版本號進行更改時, 樂觀鎖機制, 當你傳入的數據版本號(dataVersion) 和當前節點的數據版本號不符合時,zookeeper 會拒絕本次修改:eg: set /hadoop “3456” 1
version No is not valid : /hadoop

  • 刪除節點

delete path [version]
和更新節點數據一樣, 也可以傳入版本號, 當你傳入的數據版本號 (dataVersion)和當前節點的數據版本號不符合時,zookeeper 不會執行刪除操作。
要想刪除某個節點及其所有後代節點, 可以使用遞歸刪除, 命令爲 rmr path

  • 查看節點

get path

  • 查看節點狀態

可以使用 stat 命令查看節點狀態, 它的返回值和 get 命令類似, 但不會返回節點數據

  • 查看節點列表

查看節點列表有 ls path 和 ls2 path 兩個命令, 後者是前者的增強, 不僅可以查看指定路徑下的所有節點, 還可以查看當前節點的信息

  • 監聽器 get path [watch]

使用 get path [watch] 註冊的監聽器能夠在節點內容發生改變的時候, 向客戶端發出通知。 需要注意的是 zookeeper 的觸發器是一次性的 (One-time trigger), 即觸發一次後就會立即失效。

  • 監聽器stat path [watch]

使用 stat path [watch] 註冊的監聽器能夠在節點狀態發生改變的時候, 向客
戶端發出通知

  • 監聽器ls\ls2 path [watch]

使用 ls path [watch] 或 ls2 path [watch] 註冊的監聽器能夠監聽該節點下所有子節點的增加和刪除操作

zookeeper的acl權限控制

概述

  • zookeeper 類似文件系統, client 可以創建節點、 更新節點、 刪除節點,可以通過acl控制節點的權限的控制;
  • 使用scheme: id: permission 來標識, 主要涵蓋 3 個方面:

    權限模式(scheme) : 授權的策略
    授權對象(id) : 授權的對象
    權限(permission) : 授予的權限

  • 其特性如下
  • zooKeeper的權限控制是基於每個znode節點的, 需要對每個節點設置權限
  • 每個znode支持設置多種權限控制方案和多個權限
  • 子節點不會繼承父節點的權限, 客戶端無權訪問某節點, 但可能可以訪問它的子節點

權限模式

  • world 只有一個用戶: anyone, 代表登錄zokeeper所有人(默認)
  • ip 對客戶端使用IP地址認證
  • auth 使用已添加認證的用戶認證
  • digest 使用“用戶名:密碼”方式認證

授權的對象

  • 給誰授予權限
    ​- 授權對象ID是指, 權限賦予的實體, 例如: IP 地址或用戶。

授予的權限

  • create、delete、read、writer、 admin,即 增、 刪、 改、 查、 管理權限,這5種權限簡寫爲cdrwa;
    注意:這5種權限中, delete是指對子節點的刪除權限, 其它4種權限指對自身節點的操作權限
  • 授權的相關命令
    • getAcl getAcl 讀取ACL權限
    • setAcl setAcl 設置ACL權限
    • addauth addauth 添加認證用戶

zookeeper事件監聽機制

watcher概念

  • zookeeper提供了數據的發佈/訂閱功能,多個訂閱者可同時監聽某一特定主題對
    象,當該主題對象的自身狀態發生變化時(例如節點內容改變、節點下的子節點列表改變等),會實時、主動通知所有訂閱者
    ​- zookeeper採用了Watcher機制實現數據的發佈/訂閱功能。該機制在被訂閱對
    象發生變化時會異步通知客戶端,因此客戶端不必在Watcher註冊後輪詢阻塞,從而減輕了客戶端壓力。
    ​- watcher機制實際上與觀察者模式類似,也可看作是一種觀察者模式在分佈式場
    景下的實現方式。

watcher架構

Watcher實現由三個部分組成:

  • Zookeeper服務端
  • Zookeeper客戶端
  • 客戶端的ZKWatchManager對象

客戶端首先將Watcher註冊到服務端,同時將Watcher對象保存到客戶端的Watch管
理器中。當ZooKeeper服務端監聽的數據狀態發生變化時,服務端會主動通知客戶端,接着客戶端的Watch管理器會觸發相關Watcher來回調相應處理邏輯,從而完成整體的數據發佈/訂閱流程
流程

watcher特性特性

watcher接口設計

Watcher是一個接口,任何實現了Watcher接口的類就是一個新的Watcher。Watcher內部包含了兩個枚舉類:KeeperState、EventType
watcher

  • Watcher通知狀態(KeeperState)
    KeeperState是客戶端與服務端連接狀態發生變化時對應的通知類型。路徑爲
    org.apache.zookeeper.Watcher.Event.KeeperState,是一個枚舉類,其枚舉屬性
    如下:
    枚舉
  • Watcher事件類型(EventType)
    EventType是數據節點(znode)發生變化時對應的通知類型。EventType變化時
    KeeperState永遠處於SyncConnected通知狀態下;當KeeperState發生變化時,
    EventType永遠爲None。其路徑爲org.apache.zookeeper.Watcher.Event.EventType,
    是一個枚舉類,枚舉屬性如下:
    枚舉
    注:客戶端接收到的相關事件通知中只包含狀態及類型等信息,不包括節點變化前後的具體內容,變化前的數據需業務自身存儲,變化後的數據需調用get等方法重新獲取;

應用

瞭解完zk的基本特性,據此分析一下具體的使用場景案例

配置中心

eg: 數據庫用戶名和密碼信息放在一個配置文件中,應用讀取該配置文件,配置文件信息放入緩存。若數據庫的用戶名和密碼改變時候,還需要重新加載緩存,比較麻煩,通過ZooKeeper可以輕鬆完成,當數據庫發生變化時自動完成緩存同步。
設計思路:

  1. 連接zookeeper服務器
  2. 讀取zookeeper中的配置信息,註冊watcher監聽器,存入本地變量
  3. 當zookeeper中的配置信息發生變化時,通過watcher的回調方法捕獲數據變化事件
  4. 重新獲取配置信息

生成分佈式唯一ID

在單庫單表型系統中,通常可以使用數據庫字段自帶的auto_increment屬性來自動爲每條記錄生成一個唯一的ID。但是分庫分表後,就無法在依靠數據庫的auto_increment屬性來唯一標識一條記錄了。可以用zookeeper在分佈式環境下生成全局唯一ID。
設計思路:

  1. 連接zookeeper服務器
  2. 指定路徑生成臨時有序節點
  3. 取序列號及爲分佈式環境下的唯一ID

注:生產環境,一般採用別的方式:例如雪花算法等

分佈式鎖

分佈式鎖有多種實現方式,比如通過數據庫、redis都可實現。作爲分佈式協同
工具ZooKeeper,當然也有着標準的實現方式。下面介紹在zookeeper中如何實現排他鎖。
設計思路:

  1. 每個客戶端往/Locks下創建臨時有序節點/Locks/Lock 000000001
  2. 客戶端取得/Locks下子節點,並進行排序,判斷排在最前面的是否爲自己,如果自己的鎖節點在第一位,代表獲取鎖成功
  3. 如果自己的鎖節點不在第一位,則監聽自己前一位的鎖節點。例如,自己鎖節點
    Lock 000000001
  4. 當前一位鎖節點(Lock 000000002)的邏輯
  5. 監聽客戶端重新執行第2步邏輯,判斷自己是否獲得了鎖

一致性協議:zab協議

  • zab協議 的全稱是 Zookeeper Atomic Broadcast (zookeeper原子廣播)。
  • zookeeper 是通過 zab協議來保證分佈式事務的最終一致性基於zab協議,zookeeper集羣中的角色主要有以下三類,如下表所示:​
  • zab廣播模式工作原理,通過類似兩階段提交協議的方式解決數據一致性:
  1. leader從客戶端收到一個寫請求
  2. leader生成一個新的事務併爲這個事務生成一個唯一的ZXID
  3. leader將這個事務提議(propose)發送給所有的follows節點
  4. follower節點將收到的事務請求加入到歷史隊列(history queue)中,併發送ack leader
  5. 當leader收到大多數follower(半數以上節點)的ack消息,leader會發送commit請求
  6. 當follower收到commit請求時,從歷史隊列中將事務請求commit

zookeeper的leader選舉

服務器狀態

  • looking:尋找leader狀態。當服務器處於該狀態時,它會認爲當前集羣中沒有
    leader,因此需要進入leader選舉狀態。
  • ​leading: 領導者狀態。表明當前服務器角色是leader。
  • following: 跟隨者狀態。表明當前服務器角色是follower。
  • observing:觀察者狀態。表明當前服務器角色是observer

服務器啓動時期的leader選舉

在集羣初始化階段,當有一臺服務器server1啓動時,其單獨無法進行和完成
leader選舉,當第二臺服務器server2啓動時,此時兩臺機器可以相互通信,每臺機器都試圖找到leader,於是進入leader選舉過程。選舉過程如下:

  1. 每個server發出一個投票。由於是初始情況,server1和server2都會將自己作爲
    leader服務器來進行投票,每次投票會包含所推舉的服務器的myid和zxid,使用(myid, zxid)來表示,此時server1的投票爲(1, 0),server2的投票爲(2, 0),然後各自將這個投票發給集羣中其他機器。
  2. 集羣中的每臺服務器接收來自集羣中各個服務器的投票。
  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選舉過程基本一致。
  • 假設正在運行的有server1、server2、server3三臺服務器,當前leader是
    server2,若某一時刻leader掛了,此時便開始Leader選舉。選舉過程如下:
  1. 變更狀態。leader掛後,餘下的服務器都會將自己的服務器狀態變更爲looking,然後開始進入leader選舉過程。
  2. 每個server會發出一個投票。在運行期間,每個服務器上的zxid可能不同,此時假定server1的zxid爲122,server3的zxid爲122,在第一輪投票中,server1和server3都會投自己,產生投票(1, 122),(3, 122),然後各自將投票發送給集羣中所有機器。
  3. 接收來自各個服務器的投票。與啓動時過程相同
  4. 處理投票。與啓動時過程相同,此時,server3將會成爲leader。
  5. 統計投票。與啓動時過程相同。
  6. 改變服務器的狀態。與啓動時過程相同。

observer角色及其配置

observer角色特點:

  1. 不參與集羣的leader選舉
  2. 不參與集羣中寫數據時的ack反饋
  • 爲了使用observer角色,在任何想變成observer角色的配置文件中加入如下配
    置:peerType=observer
  • 並在所有server的配置文件中,配置成observer模式的server的那行配置追
    加:observer,例如:server.3=192.168.60.130:2289:3389:observer

zookeeper 在java中訪問API

1、zookeeper java API

https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper

2、開源客戶端curator

https://curator.apache.org/dependency-info.html


你的鼓勵是我創作的最大動力

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章