你需要了解的zookeeper相關知識

什麼是zookeeper?

一句話描述:zookeeper是一個開源的高可靠的分佈式系統協調器

主要提供:配置管理,命名,分佈式鎖,組服務。這些服務如果在自己的分佈式應用中實現和維護起來會有很大工作量。有了zookeeper,我們可以直接拿來用它的一致性,組管理,leader選舉等功能,也可以在此基礎上構建自己的應用。

基礎知識

  • zookeeper提供的是分佈式應用所需的分佈式協同服務。它提供了一系列基本要件供分佈式應用去構建自己的高級分佈式服務。zookeeper被設計的容易對其進行編程,使用的是類似於目錄樹的一種數據模型。
  • 眾所周知,構建正確的分佈式協同服務很難,很容易產生競態條件和死鎖,zookeeper的目標就是將我們從構建自己的分佈式應用的協同器中解放出來。

設計目標

  1. 簡單。 zookeeper允許各分佈式進程間通過共享一個類似於文件目錄樹結構的有層級的命名空間來實現彼此間的協同,該命名空間是有一系列註冊數據點組成,稱為znode。和文件系統很像,所不同的是,znodes是保存在內存中,使zookeeper可以保持高性能低延遲。
  2. zookeeper實現高性能,高可用性,嚴格的順序訪問,使它可以應用於大型分佈式系統。
  3. 備份。zookeeper服務本身也是由多臺server組成的整體。各臺server互相知道彼此,他們在自己的內存中放了各server的狀態,只要server集群中一半以上的服務可用,整個zookeeper服務就是可用的。
你需要了解的zookeeper相關知識

  1. client只會連到一臺server,client和server間保持tcp連接,以發送請求,獲取響應,發送心跳,得到watch事件,一旦tcp連接斷掉,client會同另一臺server建立tcp連接。
  2. 有序。ZooKeeper會在每一個更新上打上數字標記,以表示這個ZooKeeper事務的順序。這樣以後的操作可以根據這個標記實現更高級的抽象,如同步原語。
  3. 快速。尤其是在讀操作佔大多數的場景下。ZooKeeper的讀寫速度相差大約10:1。

數據模型

前面講了,非常像文件模型。每一個node都以路徑來唯一標識。

你需要了解的zookeeper相關知識

ZooKeeper的Node可以有子Node,也可以存儲數據,存儲的數據用來處理協同,主要有狀態信息,配置,位置信息等,通常很小。一般將node稱為znode。

znode存儲的數據中有個版本號,一旦數據有更新,這個版本號會自增。client在此獲取數據時,會得到新的版本號。

znode是有版本的(version),每個znode中存儲的數據可以有多個版本,也就是一個訪問路徑中可以存儲多份數據,version號自動增加。

znode中數據的讀寫都是原子的。每個node都有訪問控制列表acl來嚴格控制誰可以做什麼。

還有一種臨時node(ephemeral nodes),這個臨時node的生存週期是創建它的session的生存週期,一旦這個session斷掉,這個臨時node就會被刪除,這是很有用的一個特性,可以用來實現分佈式鎖。 注意EPHEMERAL(臨時的)類型的目錄節點不能有子節點目錄。

狀態更新和監視

client可以在znode上設置watch,當znode的狀態變化時將觸發watch。當client和server的連接斷掉,client會收到本地提醒。這個是Zookeeper的核心特性,Zookeeper的很多功能都是基於這個特性實現的。

Zookeeper watch是一種監聽通知機制。Zookeeper所有的讀操作getData(), getChildren()和 exists()都可以設置監視(watch),監視事件可以理解為一次性的觸發器,官方定義如下: a watch event is one-time trigger, sent to the client that set the watch, whichoccurs when the data for which the watch was set changes。Watch的三個關鍵點:

  • 一次性觸發)One-time trigger

當設置監視的數據發生改變時,該監視事件會被髮送到客戶端,例如,如果客戶端調用了getData("/znode1", true) 並且稍後 /znode1 節點上的數據發生了改變或者被刪除了,客戶端將會獲取到 /znode1 發生變化的監視事件,而如果 /znode1 再一次發生了變化,除非客戶端再次對/znode1 設置監視,否則客戶端不會收到事件通知。

  • 發送至客戶端)Sent to the client

Zookeeper客戶端和服務端是通過 socket 進行通信的,由於網絡存在故障,所以監視事件很有可能不會成功地到達客戶端,監視事件是異步發送至監視者的,Zookeeper 本身提供了順序保證(ordering guarantee):即客戶端只有首先看到了監視事件後,才會感知到它所設置監視的znode發生了變化(a client will never see a change for which it has set a watch until it first sees the watch event)。網絡延遲或者其他因素可能導致不同的客戶端在不同的時刻感知某一監視事件,但是不同的客戶端所看到的一切具有一致的順序。

  • 被設置 watch 的數據)The data for which the watch was set

這意味著znode節點本身具有不同的改變方式。你也可以想象 Zookeeper 維護了兩條監視鏈表:數據監視和子節點監視(data watches and child watches) getData() 和exists()設置數據監視,getChildren()設置子節點監視。或者你也可以想象 Zookeeper 設置的不同監視返回不同的數據,getData() 和 exists() 返回znode節點的相關信息,而getChildren() 返回子節點列表。因此,setData() 會觸發設置在某一節點上所設置的數據監視(假定數據設置成功),而一次成功的create() 操作則會出發當前節點上所設置的數據監視以及父節點的子節點監視。一次成功的 delete操作將會觸發當前節點的數據監視和子節點監視事件,同時也會觸發該節點父節點的child watch。

Zookeeper 中的監視是輕量級的,因此容易設置、維護和分發。當客戶端與 Zookeeper 服務器失去聯繫時,客戶端並不會收到監視事件的通知,只有當客戶端重新連接後,若在必要的情況下,以前註冊的監視會重新被註冊並觸發,對於開發人員來說這通常是透明的。只有一種情況會導致監視事件的丟失,即:通過exists()設置了某個znode節點的監視,但是如果某個客戶端在此znode節點被創建和刪除的時間間隔內與zookeeper服務器失去了聯繫,該客戶端即使稍後重新連接 zookeeper服務器後也得不到事件通知。

session

你需要了解的zookeeper相關知識

如果Client因為Timeout和Zookeeper Server失去連接,client處在CONNECTING狀態,會自動嘗試再去連接Server,如果在session有效期內再次成功連接到某個Server,則回到CONNECTED狀態。

注意:如果因為網絡狀態不好,client和Server失去聯繫,client會停留在當前狀態,會嘗試主動再次連接Zookeeper Server。client不能宣稱自己的session expired,session expired是由Zookeeper Server來決定的,client可以選擇自己主動關閉session。

保證

  • 一致性。按照client發送請求的順序執行。
  • 原子性。
  • 單系統視圖。不管client連到哪臺server,它看到的服務視圖都是一致的。
  • 可靠性。
  • 實時性。

api

ZooKeeper的設計目標有一個是簡單性,所以它提供的api也設計的很簡單。

  • create。創建一個node
  • delete。
  • exists。判斷在這個location是否存在node
  • get data。從node獲取數據。
  • set data。向node寫數據。
  • get children。獲取該node的子列表。
  • sync。等待數據傳播完成。

實現

你需要了解的zookeeper相關知識

上圖為ZooKeeper服務的抽象組件。每個server都會有一份自己的組件。

replicated database是內存數據庫,存放著整個service數據。也就是說每個server都有全部的信息。更新操作會記日誌到硬盤中已備恢復。寫操作是先序列化到硬盤中,再應用到內存數據庫。

從上圖可以看出,讀操作是直接從該client連的server 執行。

寫操作要通過一致性協議來執行。

所有的寫操作都會被轉發到leader,由leader進行轉發。所以ZooKeeper的讀能力比寫強大很多。

信息轉發這層稱為messaging層,負責維持leader和同步follower與leader的信息。messaging層使用原子性的信息協議,messaging層是原子性的,所以他可以保證每一個本地的信息複製都是可靠地。當leader收到一個寫請求,計算寫請求提交時的系統狀態,然後將其轉為一個投票事務,再計算新的狀態(後面詳細講解)。

原子化廣播(atomic broadcast)保證了每一個進程按照相同的順序投遞同一個消息。


分享到:


相關文章: