Zookeeper分佈式集羣原理與功能

Zookeeper功能簡介

ZooKeeper 是一個開源的分佈式協調服務,由雅虎建立,是 Google Chubby 的開源實現。 分佈式應用程序能夠基於 ZooKeeper 實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協 調/通知、集羣管理、Master 選舉、分佈式鎖和分佈式隊列 等功能。算法

Zookeeper基本概念

集羣角色

  • Leader (領導)
  • Follower (追隨者)
  • Observer (觀察員)

一個 ZooKeeper 集羣同一時刻只會有一個 Leader,其餘都是 Follower 或 Observer。ZooKeeper 配置很簡單,每一個節點的配置文件(zoo.cfg)都是同樣的,只有 myid 文件不同。myid 的值必須是 zoo.cfg中server.{數值} 的{數值}部分。數據庫

zoo.cfg 配置示例設計模式

dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logdata

tickTime=2000
initLimit=5
syncLimit=2
clientPort=2181
#集羣配置
server.0=192.168.1.100:2888:3888
server.1=192.168.1.101:2888:3888
server.2=192.168.1.102:2888:3888

在裝有 ZooKeeper 的機器的終端執行 zookeeper-server status 能夠看當前節點的 ZooKeeper是什麼角色(Leader or Follower)。服務器

節點讀寫服務分工

  1. ZooKeeper 集羣的全部機器經過一個 Leader 選舉過程來選定一臺被稱爲『Leader』 的機器,Leader服務器爲客戶端提供讀和寫服務。網絡

  2. Follower 和 Observer 都能提供讀服務,不能提供寫服務。二者惟一的區別在於, Observer機器不參與 Leader 選舉過程,也不參與寫操做的『過半寫成功』策略,因 此 Observer 能夠在不影響寫性能的狀況下提高集羣的讀性能。session

session

  1. Session 是指客戶端會話,在講解客戶端會話以前,咱們先來了解下客戶端鏈接。在 ZooKeeper 中,一個客戶端鏈接是指客戶端和 ZooKeeper 服務器之間的TCP長鏈接。併發

  2. ZooKeeper 對外的服務端口默認是2181,客戶端啓動時,首先會與服務器創建一個TCP 鏈接,從第一次鏈接創建開始,客戶端會話的生命週期也開始了,經過這個鏈接,客戶端可以通 過心跳檢測和服務器保持有效的會話,也可以向 ZooKeeper 服務器發送請求並接受響應,同 時還能經過該鏈接接收來自服務器的 Watch 事件通知。負載均衡

  3. Session 的 SessionTimeout 值用來設置一個客戶端會話的超時時間。當因爲服務器 壓力太大、網絡故障或是客戶端主動斷開鏈接等各類緣由致使客戶端鏈接斷開時,只要在 SessionTimeout 規定的時間內可以從新鏈接上集羣中任意一臺服務器,那麼以前建立的會話 仍然有效。框架

數據節點

zookeeper的結構其實就是一個樹形結構,leader就至關於其中的根結點,其它節點就至關於 follow節點,每一個節點都保留本身的數據在內存中。異步

zookeeper的節點分兩類:持久節點和臨時節點

  • 持久節點 :僅顯式刪除才消失;持久節點是指一旦這個 樹形結構上被建立了,除非主動進行對樹節點的移除操 做,不然這個 節點將一直保存在 ZooKeeper 上。

  • 臨時節點 : 會話終止即自動消失;臨時節點的生命週期跟客戶端會話綁定,一旦客戶端會話失效,那麼這個客戶端創 建的全部臨時節點都會被移除。

狀態信息

每一個節點除了存儲數據內容以外,還存儲了 節點自己的一些狀態信息。用 get 命令能夠 同時得到某個 節點的內容和狀態信息 在 ZooKeeper 中,version 屬性是用來實現樂觀鎖機制中的『寫入校驗』的(保證分佈 式數據原子性操做)。

事務操做

在ZooKeeper中,能改變ZooKeeper服務器狀態的操做稱爲事務操做。通常包括數據節點 建立與刪除、數據內容更新和客戶端會話建立與失效等操做。對應每個事務請求,ZooKeeper 都會爲其分配一個全局惟一的事務ID,用 ZXID 表示,一般是一個64位的數字。每個 ZXID 對應一次更新操做,從這些 ZXID 中能夠間接地識別出 ZooKeeper 處理這些事務操做請求的 全局順序。

Watcher(事件監聽)

事件監聽是 ZooKeeper 中一個很重要的特性。ZooKeeper容許用戶在指定節點上註冊一些 Watcher, 而且在一些特定事件觸發的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去。該 機制是 ZooKeeper 實現分佈式協調服務的重要特性。

Zookeeper應用場景

ZooKeeper 是一個高可用的分佈式數據管理與協調框架。基於對ZAB算法的實現,該框架 可以很好地保證分佈式環境中數據的一致性。也是基於這樣的特性,使得 ZooKeeper 成爲了 解決分佈式一致性問題的利器。

ZAB協議 : (zookeeper原子廣播協議),它主要支持崩潰恢復機制,在leader節點進程崩潰時當即選出新的leader,而且提供數據完整性。

數據發佈與訂閱(配置中心)

數據發佈與訂閱,即所謂的配置中心,顧名思義就是發佈者將數據發佈到 ZooKeeper 節點上, 供訂閱者進行數據訂閱,進而達到動態獲取數據的目的,實現配置信息的集中式管理和動態更新。

對於:數據量一般比較小。數據內容在運行時動態變化。集羣中各機器共享,配置一致。 這樣的全局配置信息就能夠發佈到 ZooKeeper上,讓客戶端(集羣的機器)去訂閱該消息。

發佈/訂閱系統通常有兩種設計模式,分別是推(Push)和拉(Pull)模式。

  • 推模式:服務端主動將數據更新發送給全部訂閱的客戶端
  • 拉模式:客戶端主動發起請求來獲取最新數據,一般客戶端都採用定時輪詢拉取的方式

ZooKeeper 採用的是推拉相結合的方式: 客戶端想服務端註冊本身須要關注的節點,一旦該節點的數據發生變動,那麼服務端就會向相應 的客戶端發送Watcher事件通知,客戶端接收到這個消息通知後,須要主動到服務端獲取最新的數據

命名服務

命名服務也是分佈式系統中比較常見的一類場景。在分佈式系統中,經過使用命名服務,客戶端 應用可以根據指定名字來獲取資源或服務的地址,提供者等信息。被命名的實體一般能夠是集羣中的 機器,提供的服務,遠程對象等等——這些咱們均可以統稱他們爲名字。

其中較爲常見的就是一些分佈式服務框架(如RPC)中的服務地址列表。經過在ZooKeepr裏 建立順序節點,可以很容易建立一個全局惟一的路徑,這個路徑就能夠做爲一個名字。
ZooKeeper 的命名服務即生成全局惟一的ID。

分佈式協調服務/通知

ZooKeeper 中特有 Watcher 註冊與異步通知機制,可以很好的實現分佈式環境下不一樣機器, 甚至不一樣系統之間的通知與協調,從而實現對數據變動的實時處理。使用方法一般是不一樣的客戶端 若是 機器節點 發生了變化,那麼全部訂閱的客戶端都可以接收到相應的Watcher通知,並作出相應 的處理。 ZooKeeper的分佈式協調/通知,是一種通用的分佈式系統機器間的通訊方式。

master選舉

Master 選舉能夠說是 ZooKeeper 最典型的應用場景了。好比 HDFS 中 Active NameNode 的選舉、YARN 中 Active ResourceManager 的選舉和 HBase 中 Active HMaster 的選舉等。

針對 Master 選舉的需求,一般狀況下,咱們能夠選擇常見的關係型數據庫中的主鍵特性來 實現:但願成爲 Master 的機器都向數據庫中插入一條相同主鍵ID的記錄,數據庫會幫咱們進行 主鍵衝突檢查,也就是說,只有一臺機器能插入成功——那麼,咱們就認爲向數據庫中成功插入數據 的客戶端機器成爲Master。

依靠關係型數據庫的主鍵特性確實可以很好地保證在集羣中選舉出惟一的一個Master。

可是,若是當前選舉出的 Master 掛了,那麼該如何處理?誰來告訴我 Master 掛了呢? 顯然,關係型數據庫沒法通知咱們這個事件。可是,ZooKeeper 能夠作到!

利用 ZooKeepr 的強一致性,可以很好地保證在分佈式高併發狀況下節點的建立必定可以 保證全局惟一性,即 ZooKeeper 將會保證客戶端沒法建立一個已經存在的 數據單元節點。 也就是說,若是同時有多個客戶端請求建立同一個臨時節點,那麼最終必定只有一個客戶端 請求可以建立成功。利用這個特性,就能很容易地在分佈式環境中進行 Master 選舉了。

成功建立該節點的客戶端所在的機器就成爲了 Master。同時,其餘沒有成功建立該節點的 客戶端,都會在該節點上註冊一個子節點變動的 Watcher,用於監控當前 Master 機器是否存 活,一旦發現當前的Master掛了,那麼其餘客戶端將會從新進行 Master 選舉,這樣就實現了 Master 的動態選舉。

分佈式鎖

分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式 ,分佈式鎖又分爲排他鎖和共享鎖兩種

排它鎖 :ZooKeeper如何實現排它鎖

  • 定義鎖:ZooKeeper 上的一個 機器節點 能夠表示一個鎖

  • 得到鎖:把ZooKeeper上的一個節點看做是一個鎖,得到鎖就經過建立臨時節點的方式來實現。ZooKeeper 會保證在全部客戶端中,最終只有一個客戶端可以建立成功,那麼就能夠認爲該客戶端得到了鎖。同時,全部沒有獲取到鎖的客戶端就須要到/exclusive_lock
    節點上註冊一個子節點變動的Watcher監聽,以便實時監聽到lock節點的變動狀況。

  • 釋放鎖:由於鎖是一個臨時節點,釋放鎖有兩種方式
  1. 當前得到鎖的客戶端機器發生宕機或重啓,那麼該臨時節點就會被刪除,釋放鎖
  2. 正常執行完業務邏輯後,客戶端就會主動將本身建立的臨時節點刪除,釋放鎖。

不管在什麼狀況下移除了lock節點,ZooKeeper 都會通知全部在 /exclusive_lock 節點上註冊了節點變動 Watcher 監聽的客戶端。這些客戶端在接收到通知後,再次從新發起分佈式鎖獲取,即重複『獲取鎖』過程。

共享鎖

共享鎖在同一個進程中很容易實現,可是在跨進程或者在不一樣 Server 之間就很差實現了。Zookeeper 卻很容易實現這個功能,實現方式也是須要得到鎖的 Server 建立一個 EPHEMERAL_SEQUENTIAL 目錄節點,而後調用 getChildren方法獲取當前的目錄節點列表中最小的目錄節點是否是就是本身建立的目錄節點,若是正是本身建立的,那麼它就得到了這個鎖,若是不是那麼它就調用 exists(String path, boolean watch) 方法並監控 Zookeeper 上目錄節點列表的變化,一直到本身建立的節點是列表中最小編號的目錄節點,從而得到鎖,釋放鎖很簡單,只要刪除前面它本身所建立的目錄節點就好了。

相關文章
相關標籤/搜索