1. 程式人生 > >13、Zookeeper 分散式叢集管理技術

13、Zookeeper 分散式叢集管理技術

1.Zookeeper 簡介

Zookeeper 分散式服務框架主要是用來解決分散式應用中經常遇到的一些資料管理問題,提供分散式、高可用性的協調服務能力,在 FusionInsight 叢集中主要用途是儲存上層元件的元資料,並保證其主備倒換。

Zookeeper 的作用

(1) 配置管理這個好理解。分散式系統都有好多機器,比如我在搭建 hadoop 的 HDFS 的時候,需要在一個主機器上(Master 節點)配置好 HDFS 需要的各種配置檔案,然後通過 scp 命令把這些配置檔案拷貝到其他節點上,這樣各個機器拿到的配置資訊是一致的,才能成功執行起來 HDFS 服務。 Zookeeper 提供了這樣的一種服務:一種集中管理配置的方法,我們在這個集中的地方修改了配置,所有對這個配置感興趣的都可以獲得變更。這樣就省去手動拷貝配置了,還保證了可靠和一致性。這裡寫圖片描述

(2) 名字服務這個可以簡單理解為一個電話薄,電話號碼不好記,但是人名好記,要打誰的電話,直接查人名就好了。分散式環境下,經常需要對應用/服務進行統一命名,便於識別不同服務;類似於域名與 ip 之間對應關係,域名容易記住;通過名稱來獲取資源或服務的地址,提供者等資訊

(3) 分散式鎖,單機程式的各個程序需要對互斥資源進行訪問時需要加鎖,那分散式程式分佈在各個主機上的程序對互斥資源進行訪問時也需要加鎖。很多分散式系統有多個可服務的視窗,但是在某個時刻只讓一個服務去幹活,當這臺服務出問題的時候鎖釋放,立即 failover 到另外的服務。這在很多分散式系統中都是這麼做,這種設計有一個更好聽的名字叫

LeaderElection(leader 選舉)。舉個通俗點的例子,比如銀行取錢,有多個視窗,但是呢對你來說,只能有一個視窗對你服務,如果正在對你服務的視窗的櫃員突然有急事走了,那咋辦?找大堂經理(zookeeper)!大堂經理指定另外的一個視窗繼續為你服務!

(4) 叢集管理,在分散式的叢集中,經常會由於各種原因,比如硬體故障,軟體故障,網路問題,有些節點會進進出出。有新的節點加入進來,也有老的節點退出叢集。這個時候,叢集中有些機器(比如 Master 節點)需要感知到這種變化,然後根據這種變化做出對應的決策。我已經知道 HDFS 中 namenode 是通過 datanode 的心跳機制來實現上述感知的,那麼我們可以先假設 Zookeeper 其實也是實現了類似心跳機制的功能吧!

Zookeeper 的特點

(1) 最終一致性:為客戶端展示同一檢視,這是 zookeeper 最重要的功能。

(2) 可靠性:如果訊息被到一臺伺服器接受,那麼它將被所有的伺服器接受。

(3) 實時性:Zookeeper 不能保證兩個客戶端能同時得到剛更新的資料,如果需要最新資料,應該在讀資料之前呼叫 sync()介面。

(4) 等待無關(wait-free):慢的或者失效的 client 不干預快速的 client 的請求。

(5) 原子性:更新只能成功或者失敗,沒有中間狀態。(6) 順序性:所有 Server,同一訊息釋出順序一致。用到 Zookeeper 的系統(1) HDFS 中的 HA 方案(2) YARN 的 HA 方案

(3) HBase:必須依賴 Zookeeper,儲存了 Regionserver 的心跳資訊,和其他的一些關鍵資訊。

(4) Flume:負載均衡,單點故障。

2.Zookeeper 服務框架

(1) ZooKeeper 叢集由一組 Server 節點組成,這一組 Server 節點中存在一個角色為 Leader 的節點,其他節點都為 Follower。當客戶端 Client 連線到 ZooKeeper 叢集,並且執行寫請求時,這些請求會被髮送到 Leader 節點上,然後 Leader 節點上資料變更會同步到叢集中其他的 Follower 節點。

(2) Leader 節點在接收到資料變更請求後,首先將變更寫入本地磁碟,以作恢復之用。當所有的寫請求持久化到磁碟以後,才會將變更應用到記憶體中。(3) ZooKeeper   使  用  了  一  種  自  定  義  的  原  子  消  息  協  議(ZookeeperAtomicBroadcas  Zab 協議),在訊息層的這種原子特性,保證了整個協調系統中的節點資料或狀態的一致性。Follower 基於這種訊息協議能夠保證本地的 ZooKeeper 資料與 Leader 節點同步,然後基於本地的儲存來獨立地對外提供服務。

(4) 當一個 Leader 節點發生故障失效時,失敗故障是快速響應的,訊息層負責重新選擇一個 Leader,繼續作為協調服務叢集的中心,處理客戶端寫請求,並將 ZooKeeper 協調系統的資料變更同步(廣播)到其他的 Follower 節點。

3.Zookeeper 資料模型

 

每個節點(znode)中儲存的是同步相關的資料(這是 ZooKeeper 設計的初衷,資料量很小,大概 B 到 KB 量級),例如狀態資訊、配置內容、位置資訊等。一個 znode 維護了一個狀態結構,該結構包括:版本號、ACL 變更、時間戳。每次 znode 資料發生變化,版本號都會遞增,這樣客戶端的讀請求可以基於版本號來檢索狀態相關資料。每個 znode 都有一個 ACL,用來限制是否可以訪問該 znode。在一個名稱空間中,對 znode 上儲存的資料執行讀和寫請求操作都是原子的。客戶端可以在一個 znode 上設定一個監視器(Watch),如果該 znode 資料發生變更,ZooKeeper 會通知客戶端,從而觸發監視器中實現的邏輯的執行。每個客戶端與 ZooKeeper 連線,便建立了一次會話(Session),會話過程中,可能發生 CONNECTING、CONNECTED 和 CLOSED 三種狀態。ZooKeeper 支援臨時節點(EphemeralNodes)的概念,它是與 ZooKeeper 中的會話(Session)相關的,如果連線斷開,則該節點被刪除。若非操作人員刪除,永久節點會永久儲存,所以永久節點可以用來儲存元資料,而臨時節點則可用來進行 leader 選舉及鎖服務等。

Zookeeper 的主流應用場景實現思路

(1)配置管理

集中式的配置管理在應用叢集中是非常常見的,一般商業公司內部都會實現一套集中的配置管理中心,應對不同的應用叢集對於共享各自配置的需求,並且在配置變更時能夠通知到叢集中的每一個機器。Zookeeper 很容易實現這種集中式的配置管理,比如將 APP1 的所有配置配置到/APP1znode 下,APP1 所有機器一啟動就對/APP1 這個節點進行監控(zk.exist("/APP1",true)),並且實現回撥方法 Watcher,那麼在 zookeeper 上 /APP1znode 節點下資料發生變化的時候,每個機器都會收到通知,Watcher 方法將會被執行,那麼應用再取下資料即可(zk.getData("/APP1",false,null));以上這個例子只是簡單的粗顆粒度配置監控,細顆粒度的資料可以進行分層級監控,這一切都是可以設計和控制的

(2)叢集管理

應用叢集中,我們常常需要讓每一個機器知道叢集中(或依賴的其他某一個叢集)哪些機器是活著的,並且在叢集機器因為宕機,網路斷鏈等原因能夠不在人工介入的情況下迅速通知到每一個機器。Zookeeper 同樣很容易實現這個功能,比如我在 zookeeper 伺服器端有一個 znode叫/APP1SERVERS,那麼叢集中每一個機器啟動的時候都去這個節點下建立一個EPHEMERAL 型別的節點,比如 server1 建立/APP1SERVERS/SERVER1(可以使用 ip, 保證不重複),server2 建立/APP1SERVERS/SERVER2,然後 SERVER1 和 SERVER2 都 watch/APP1SERVERS 這個父節點,那麼也就是這個父節點下資料或者子節點變化都會通知對該節點進行 watch 的客戶端。因為 EPHEMERAL 型別節點有一個很重要的特性,就是客戶端和伺服器端連線斷掉或者 session 過期就會使節點消失,那麼在某一個機器掛掉或者斷鏈的時候,其對應的節點就會消失,然後叢集中所有對/APP1SERVERS 進行 watch 的客戶端都會收到通知,然後取得最新列表即可。另外有一個應用場景就是叢集選 master,一旦 master 掛掉能夠馬上能從 slave 中選出一個 master,實現步驟和前者一樣,只是機器在啟動的時候APP1SERVERS 建立的節點型別變為 EPHEMERAL_SEQUENTIAL 型別,這樣每個節點會自動被編號我們預設規定編號最小的為 master,所以當我們對/APP1SERVERS節點做監控的時候,得到伺服器列表,只要所有叢集機器邏輯認為最小編號節點為 master,那麼 master 就被選出,而這個 master 宕機的時候,相應的 znode 會消失,然後新的伺服器列表就被推送到客戶端,然後每個節點邏輯認為最小編號節點為 master,這樣就做到動態 master 選舉。

4.Zookeeper 的容災能力

一般情況下,ZooKeeper 能夠完成選舉即能夠正常對外提供服務。ZooKeeper 選舉時,當某一個例項獲得了半數以上的票數時,則變為 leader。對於 n 個例項的服務,n 可能為奇數或偶數 n 為奇數時,假定 n=2x+1,則成為 leader 的節點需獲得 x+1 票,容災能力為 x。 n 為偶數時,假定 n=2x+2,則成為 leader 的節點需要獲得 x+2 票(大於一半),容災能力為 x。由此可見,2x+1 個節點與 2x+2 個節點的容災能力相同(3 個與 4 個相同,5 個與 6 個相同…),而考慮到選舉以及完成寫操作的速度與節點數的相關性,我們建議 ZooKeeper 部署奇數個節點。Zookeeper 的選舉是使用舉手表決制的,誰的票超過半數誰就獲勝。這個機制不僅用於選舉,也用於內部的各種業務中,所以節點的數量對於業務的執行是很重要的。比如,我們現在有三個節點 ABC,那麼 A 如果要成為組長它只需要得到 B 或者 C 中的一票就可以獲勝,這個時候如果 B 或者 C 中損壞一個節點,對於 A 來說都是沒有影響的,損壞的節點我們可以理解為棄權,A 獲取剩下的節點的一票仍然是可以當選的,沒有影響到現有的業務正常執行。我們允許損壞一個節點繼續執行業務。但是現在如果有 4 個節點 ABCD,那麼 A 如果想要成為組長,它就必須得到 BCD 中的兩票超過半數才行。這個時候如果 D 損壞了,那麼 A 仍舊是需要的到 BC 的兩票即可,業務正常執行。但是如果此時 C 也損壞了,那麼 A 得到自己和 B 的票之後,沒有超過半數,那麼業務就無法正常執行了。所以 4 節點情況下,我們最多損壞一個節點。如果現在有 5 個節點 ABCDE,那麼同上,我們為了保證半數以上節點存活,最多可以允許 2 個節點損壞。這裡原因不在贅述。所以我們可以發現,當節點數是 3 個和 4 個的時候,他們都只能允許損壞 1 個節點,容災能力是相同的,5 節點的時候容災能力+1,所以我們說,儘量建議部署為奇數個節點。這樣對於容災性和資料的讀寫速度來說,都是有更好的提升的。

5.Zookeeper 關鍵特性

(1) 最終一致性:無論哪個 server,對外展示的均是同一個檢視。

(2) 實時性:保證客戶端將在一個時間間隔範圍內獲得伺服器的更新資訊,或者伺服器失效的資訊。

(3) 可靠性:一條訊息被一個 server 接收,它將被所有 server 接受。

(4) 原子性:更新只能成功或者失敗,沒有中間狀態。

(5) 順序一致性:客戶端所傳送的更新會按照它們被髮送的順序進行應用。

6.Zookeeper 的讀寫特性

(1)讀特性

 

由 ZooKeeper 的一致性可知,客戶端無論連線哪個 server,獲取的均是同一個檢視。所以,讀操作可以在客戶端與任意節點間完成。

(2)寫特性

上圖中展示的是寫請求的處理過程:編號 1~5 表示具體步驟

(1) 同讀請求一樣,客戶端可以向任一 server 提出寫請求。

(2) server 將這一請求傳送給 leader。

(3) leader 獲取寫請求後,會向所有節點發送這條寫請求資訊,詢問是否能夠執行這次寫操作。

(4) follower 節點根據自身情況給出反饋資訊 ACK 應答訊息,leader 根據反饋資訊,若獲取到的可以執行寫操作的數量大於例項總數的一半,則認為本次寫操作可執行。

(5) leader 將結果反饋給各 follower,並完成寫操作,各 follower 節點同步 leader 的資料,本次寫操作完成。

7.Zookeeper—ACL

ACL 可以控制訪問 ZooKeeper 的節點,只能應用於特定的 znode 上,而不能應用於該 znode 的所有子節點上。設定 ACL 命令為 setAcl/znodescheme:id:perm。 Scheme 為認證方式,ZooKeeper 內建了 4 種方式:

(1) world 一個單獨的 ID,表示任何人都可以訪問。

(2) auth 不使用 ID,只有認證的使用者可以訪問。

(3)     digest 使用 username:password 生成 MD5 雜湊值作為認證 ID。

(4) IP 使用客戶端主機 IP 地址來進行認證。Id:用來認證的欄位,用來判斷認證資訊是否合法,不同的 scheme 的認證方式不同。

Perm:即 permission,通過 Acl 認證的使用者對該節點可擁有的操作許可權。