ZooKeeper 基礎入門

程式設計師cxuan發表於2020-06-06

什麼是ZooKeeper

Apache ZooKeeper 是一個開源的實現高可用的分散式協調伺服器。ZooKeeper是一種集中式服務,用於維護配置資訊,域名服務,提供分散式同步和叢集管理。所有這些服務的種類都被應用在分散式環境中,每一次實施這些都會做很多工作來避免出現bug和競爭條件。

ZooKeeper 設計原則

ZooKeeper 很簡單

ZooKeeper 允許分散式程式通過共享的分層名稱空間相互協調,ZooKeeper名稱空間與檔案系統很相似,每個名稱空間填充了資料節點的註冊資訊 - 叫做Znode,這是在 ZooKeeper 中的叫法,Znode 很像我們檔案系統中的檔案和目錄。ZooKeeper 與典型的檔案系統不同,ZooKeeper 資料儲存在記憶體中,這意味著 ZooKeeper 可以實現高吞吐量和低時延。

ZooKeeper 可複製

與它協調的分散式程式一樣,ZooKeeper本身也可以在稱為叢集的一組主機上進行復制。

組成 ZooKeeper 服務的單個服務端必須瞭解彼此。它們維護記憶體中的狀態、永續性的事務日誌和快照。只要大多數服務可用,ZooKeeper 服務就可用。

客戶端可以連線到單個的伺服器。客戶端通過連線單個伺服器進而維護 TCP 連線,通過連線傳送請求,獲取響應,獲取監聽事件以及傳送心跳,很像Eureka Server 的功能。如果與單個伺服器的連線中斷,客戶端會自動的連線到ZooKeeper Service 中的其他伺服器。

ZooKeeper 有序

ZooKeeper使用時間戳來記錄導致狀態變更的事務性操作,也就是說,一組事務通過時間戳來保證有序性。基於這一特性。ZooKeeper可以實現更加高階的抽象操作,如同步等。

ZooKeeper 非常快

ZooKeeper包括讀寫兩種操作,基於ZooKeeper的分散式應用,如果是讀多寫少的應用場景(讀寫比例大約是10:1),那麼讀效能更能夠體現出高效。

ZooKeeper基本概念

資料模型和分層名稱空間

ZooKeeper提供的名稱空間非常類似於標準檔案系統。名稱是由斜槓(/)分隔的路徑元素序列。 ZooKeeper名稱空間中的每個節點都由路徑標識。

ZooKeeper的分層名稱空間圖

節點和臨時節點

與標準的檔案系統所不同的是,ZooKeeper名稱空間中的每個節點都可以包含與之關聯的資料以及子項,這就像一個檔案也是目錄的檔案系統。ZooKeeper被設計用來儲存分散式資料:狀態資訊,配置,定位資訊等等。所以每個ZooKeeper 節點能儲存的容量非常小,最大容量為 1MB。我們使用術語 Znode 來表明我們正在談論ZooKeeper資料節點。

Znodes 維護了一個 stat 結構,包括資料變更,ACL更改和時間戳的版本號,用來驗證快取和同步更新。每一次Znode 的資料發生了變化,版本號的數量就會進行增加。每當客戶端檢索某個znode 資料時,它也會接收該資料的版本。

名稱空間下資料儲存的Znode 節點都會以原子性的方式讀寫,也就是保證了原子性。讀取所有Znode 相關聯的節點資料並通過寫的方式替換節點資料。每一個節點都會有一個 訪問控制列表(ACL)的限制來判斷誰可以進行操作。

ZooKeeper 也有臨時節點的概念。只要建立的 Znode 的會話(session)處於活動狀態,就會存在這些臨時節點。當會話結束,臨時節點也就被刪除。

選擇性更新和watches

ZooKeeper支援watches的概念。客戶端可以在 Znode 上設定監聽。當 Znode 發生變化時,監聽會被觸發並移除。觸發監聽時,客戶端會收到一個資料包告知 Znode 發生變更。如果客戶端與其中一個 ZooKeeper 伺服器之間的連線中斷,則客戶端將收到本地通知。

叢集角色

通常在分散式系統中,構成一個叢集中的每一臺機器都有一個自己的角色,最典型的叢集模式就是 master/slave (主備模式)。在這種模式中,我們把能夠處理寫操作請求的機器成為 Master ,把所有通過非同步複製方式獲取最新資料,並提供讀請求服務的機器成為 Slave 機器。

而 ZooKeeper 沒有采用這種方式,ZooKeeper 引用了 Leader、Follower和 Observer 三個角色。ZooKeeper 叢集中的所有機器通過選舉的方式選出一個 Leader,Leader 可以為客戶端提供讀服務和寫服務。除了 Leader 外,叢集中還包括了 Follower 和 Observer 。Follower 和 Observer 都能夠提供讀服務,唯一區別在於,**Observer ** 不參與 Leader 的選舉過程,也不寫操作的"過半寫成功"策略,因此 Observer 可以在不影響寫效能的情況下提升叢集的讀效能。

Session

Session 指的是客戶端會話,在講解會話之前先來了解一下客戶端連線。客戶端連線指的就是客戶端和伺服器之間的一個 TCP長連線,ZooKeeper 對外的埠是 2181,客戶端啟動的時候會與伺服器建立一個 TCP 連線,從第一次連線建立開始,客戶端會話的生命週期也就開始了,通過這個連線,客戶端能夠通過心跳檢測與伺服器保證有效的會話,也能夠向 ZooKeeper 伺服器傳送請求並接受響應,同時還能夠通過該連線來接收來自伺服器的Watch 事件通知。

ZooKeeper 特性

一致性要求

ZooKeeper 非常快並且很簡單。但是,由於其開發的目的在於構建更復雜的服務(如同步)的基礎,因此它提供了一系列的保證,這些保證是:

  • 順序一致性:客戶端的更新將按順序應用。
  • 原子性:更新要麼成功要麼失敗,沒有其他結果
  • 單一檢視:無論客戶端連線到哪個服務,所看到的環境都是一樣的
  • 可靠性:開始更新後,它將從該時間開始,一直到客戶端覆蓋更新
  • 及時性: 系統的客戶檢視保證在特定時間範圍內是最新的。

簡單的API使用

ZooKeeper 設計之初提供了非常簡單的程式設計介面。作為結果,它支援以下操作:

  • create:在文件目錄樹中的某一個位置建立節點
  • delete: 刪除節點
  • exists: 測試某個位置是否存在節點
  • get data: 從節點中讀取資料
  • set data: 向節點中寫資料
  • get children: 從節點中檢索子節點列表
  • sync: 等待資料傳播

實現

ZooKeeper Components 展現了ZooKeeper 服務的高階元件。除請求處理器外,構成 ZooKeeper 服務的每個伺服器都複製其自己的每個元件的副本。


圖中的 Replicated Database (可複製的資料庫)是一個包含了整個資料樹的記憶體資料庫。更新將記錄到磁碟以獲得可恢復性,並且寫入在應用到記憶體資料庫之前會得到序列化。

每一個 ZooKeeper 伺服器都為客戶端服務。客戶端只連線到一臺伺服器用以提交請求。讀請求由每個伺服器資料庫的本地副本提供服務,請求能夠改變服務的狀態,寫請求由"同意協議"進行通過。

作為"同意協議" 的一部分,所有的請求都遵從一個單個的服務,由這個服務來詢問除自己之外其他服務是否可以同意寫請求,而這個單個的服務被稱為Leader。除自己之外其他的服務被稱為follower,它們接收來自Leader 的訊息並對訊息達成一致。訊息傳底層負責替換失敗的 leader 並使 follower 與 leader 進行同步。

ZooKeeper 使用自定義的原子性訊息傳遞協議。因為訊息傳底層是原子性的,ZooKeeper 能夠保證本地副本永遠不會產生分析或者衝突。當 leader 接收到寫請求時,它會計算系統的狀態以確保寫請求何時應用,並且開啟一個捕獲新狀態的事務。

使用者

ZooKeeper 的程式設計介面非常簡單,但是通過它,你可以實現更高階的操作。

效能

ZooKeeper 旨在提供高效能,但是真的是這樣嗎?ZooKeeper是由雅虎團隊開發。當讀請求遠遠高於寫請求的時候,它的效率很高,因為寫操作涉及同步所有伺服器的狀態。(讀取數量超過寫入通常是協調服務的情況。)

ZooKeeper吞吐量作為讀寫比率變化是在具有雙2Ghz Xeon和兩個SATA 15K RPM驅動器的伺服器上執行的ZooKeeper版本3.2的吞吐量圖。一個驅動器用作專用的ZooKeeper日誌裝置。快照已寫入OS驅動器。寫請求是1K寫入,讀取是1K讀取。 “伺服器”表示ZooKeeper集合的大小,即構成服務的伺服器數量。 大約30個其他伺服器用於模擬客戶端。 ZooKeeper集合的配置使得Leader不允許來自客戶端的連線。(此部分來源於翻譯結果)

基準也表明它也是可靠的。 存在錯誤時的可靠性顯示了部署如何響應各種故障。 圖中標記的事件如下:

  1. follower 的失敗和恢復
  2. 失敗和恢復不同的 follower
  3. leader 的失敗
  4. 兩個follower 的失敗和恢復
  5. 其他leader 的失敗

可靠性

為了在注入故障時顯示系統隨時間的行為,我們執行了由7臺機器組成的ZooKeeper服務。我們執行與以前相同的飽和度基準,但這次我們將寫入百分比保持在恆定的30%,這是我們預期工作量的保守比率。(此部分來源於翻譯結果)

該圖中有一些重要的觀察結果。 首先,如果follower 失敗並迅速恢復,那麼即使失敗,ZooKeeper也能夠維持高吞吐量。 但也許更重要的是,leader 選舉演算法允許系統足夠快地恢復以防止吞吐量大幅下降。 在我們的觀察中,ZooKeeper 選擇新 leader 的時間不到200毫秒。 第三,隨著follower 的恢復,ZooKeeper能夠在開始處理請求後再次提高吞吐量。

文章來源:

https://zookeeper.apache.org/doc/current/zookeeperOver.html

《從Paxos到zookeeper分散式一致性原理與實踐》