1. 程式人生 > >ZooKeeper(1)--ZooKeeper概述

ZooKeeper(1)--ZooKeeper概述

參考於ZooKeeper學習第一期---Zookeeper簡單介紹

Zookeeper是什麼?

ZooKeeper是一種為分散式應用所設計的高可用高效能一致的開源協調服務,它提供了一項基本服務:分散式鎖服務

協調服務--""

Zookeeper主要應用於分散式系統,協調分散式系統下不同機器的多個執行緒對臨界資源呼叫.

如果是在同一臺機器,不同執行緒之間的協調是比較容易的.可以對臨界資源加鎖.當一個執行緒要使用這個臨界資源的時候,要先獲取,並一直獨自享有這個資源,其他程序是無法使用這個臨界資源.直到這個執行緒呼叫完這個資源或發生了異常,就會將鎖釋放,這時其他執行緒才可以再去獲取這個鎖

,來呼叫這個資源.

但是這個鎖在分散式系統中就沒有這麼"好用".

分散式系統所面臨的問題

在分散式系統中,不同的系統之間的聯絡是通過網路來進行的,這就涉及到一個問題:網路穩定性問題.

在同一臺機器中,一個執行緒呼叫服務只有兩種情況:呼叫成功和呼叫失敗,丟擲異常.但是在分散式系統,由於網路的不穩定,會出現一種情況,在一個執行緒獲取到鎖並在呼叫完之後,傳送資訊給伺服器,告訴伺服器已經完成任務,可以釋放鎖,但是由於網路原因,這個資訊丟失了,而其他執行緒一直等待著鎖的釋放,導致了死鎖.

還有一種情況,需要A,B兩個執行緒按順序呼叫服務C,在時間上 A先呼叫,B後呼叫,但是由於網路原因

,可能會導致BA先到,導致了難以預料的錯誤.

其次,在分散式環境中為了提升可靠性,我們往往會部署多套服務,但是如何在多套服務中達到一致性,這在同一臺機器上多個程序之間的同步相對來說比較容易辦到,但在分散式環境中確實一個大難題.

Zookeeper使用了分散式鎖來解決這些問題.

Zookeeper概述

那麼Zookeeper是如何實現分散式鎖的呢?除此之外,Zookeeper還通過什麼方式實現了配置維護、組服務、分散式訊息佇列分散式通知/協調服務.

Zookeeper設計了一種資料結構—Znode,然後在該資料結構的基礎上定義了一些原語,也就是一些關於該資料結構的一些操作。有了這些資料結構和原語還不夠,因為我們的

ZooKeeper是工作在一個分散式的環境下,我們的服務是通過訊息以網路的形式傳送給我們的分散式應用程式,所以還需要一個通知機制——Watcher機制。所以ZooKeeper所提供的服務主要是通過:資料結構+原語+watcher機制,三個部分來實現的.

Zookeeper的資料模型Znode

Zookeeper的結構和檔案系統非常相似,都是一種樹形結構.

ZooKeeper樹中的每個節點被稱為—Znode。和檔案系統的目錄樹一樣,ZooKeeper樹中的每個節點可以擁有子節點。但也有不同之處:

引用方式

Znode通過路徑訪問,而且必須是絕對路徑,開頭必須為"/",而不能是相對路徑,比如說想訪問Storage節點,則必須是/Baidu/Yun/Storage.字串"/zookeeper"用以儲存管理資訊,比如關鍵配額資訊。

Znode結構

Znode兼具檔案與目錄的屬性,即可以當做一個檔案:儲存一些資料,原資訊,ACL,時間戳等資訊,也可以當做一個目錄:作為路徑標識的一部分,並擁有子節點.

Znode由三部分組成:

stat:狀態資訊,描述Znode的版本,許可權的資訊

data:儲存一些資料.

children:儲存該節點的子節點.

Znode雖然又可以儲存資料的部分,但其一般不用於儲存一些普通的資料,其通常被用於儲存一些對分散式系統比較重要的排程資訊,如分散式應用中的配置檔案資訊狀態資訊彙集位置等等,而且Znode的資料大小被限制在1M以內,但常規使用中,我們儲存的資料應該遠遠小於此數值.

資料訪問

讀操作將獲取與節點相關的所有資料,寫操作也將替換掉節點的所有資料。另外,每一個節點都擁有自己的ACL(訪問控制列表),這個列表規定了使用者的許可權,即限定了特定使用者對目標節點可以執行的操作。

節點型別

Zookeeper中的節點有兩種,分別為臨時節點ephemeral永久節點persistent.節點的型別在建立的時候就會被確定,而且不能修改.

臨時節點:該節點的生命週期依賴於會話,一旦會話(session)結束,臨時節點將自動刪除,此外,臨時節點不允許有子節點.

永久節點:該節點永遠存在,不依賴域會話,只能被手動刪除,允許有子節點,且子節點可以是臨時節點,也可以是永久節點.

順序節點:當建立Znode的時候,使用者可以請求在ZooKeeper的路徑結尾新增一個遞增的計數。這個計數對於此節點的父節點來說唯一的,它的格式為"%10d"(10位數字,沒有數值的數位用0補充,例如"0000000001")。當計數值大於232-1時,計數器將溢位。

觀察

客戶端可以在節點上設定監視器,watch,其作用是在節點發生變化(增刪改查)的時候,會向客戶端傳送相對應的通知,注意的是,這個通知會且只會傳送一次.

Zookeeper的版本資訊

Zookeeper主要通過zxid屬性來維護版本資訊,致使ZooKeeper節點狀態改變的每一個操作都將使節點接收到一個Zxid格式的時間戳,並且這個時間戳全域性有序。也就是說,每個對節點的改變都將產生一個唯一的Zxid。如果Zxid1的值小於Zxid2的值,那麼Zxid1所對應的事件發生在Zxid2所對應的事件之前。

實際上,ZooKeeper的每個節點維護者三個Zxid值,為別為:cZxidmZxidpZxid

 cZxid 是節點的建立時間所對應的Zxid格式時間戳。
② mZxid:是節點的修改時間所對應的Zxid格式時間戳。

實現中Zxid是一個64為的數字,它32epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個 新的epoch32是個遞增計數 (2) 版本號

對節點的每一個操作都將致使這個節點的版本號增加。每個節點維護著三個版本號,他們分別為:

① version:節點資料版本號
② cversion:子節點版本號
③ aversion:節點所擁有的ACL版本號

 

Zookeeper的節點屬性

czxid

節點被建立的zxid

mzxid

節點被修改的zxid

ctime

節點被建立的時間

mtime

節點被修改的時間

version

節點被修改的版本號

cversion

節點所擁有的子節點被修改的版本號

aversion

節點的ACL(許可權管理)被修改的版本號

ephemeralowner

如果該節點為臨時節點,則為該節點擁有者的會話ID,否則為0

dataLength

節點數長度

numChildren

節點用的子節點長度

pzxid

該節點的子節點(或該節點)的最近一次 建立 / 刪除 的時間戳對應,只與 本節點 / 該節點的子節點,有關;與孫子節點無關。

 

Watch觸發器

ZooKeeper可以為所有的讀操作設定watch,這些讀操作包括:exists()getChildren()getData()watch事件是一次性的觸發器,每次都需要重新註冊,並且客戶端在會話異常結束時不會收到任何通知,watch的物件狀態發生改變時,將會觸發此物件上watch所對應的事件。watch事件將被非同步地傳送給客戶端.

watch來說,有三個主要特性:

  •   

一次性觸發:觀察事件會在觀察的資料改變時被主動傳送給客戶端。舉個例子,如果一個客戶端呼叫了getData("/znode1", true),也就是在/znode1上設定了一個觀察者,在這之後,如果/znode1發生了改變或者被刪除了,這個客戶端會受到觀察事件的提醒,但是,如果之後/znode1又發生了改變或者刪除,這個客戶端是不會收到事件提醒的了。

  •  

有序地傳送給客戶端watch事件非同步傳送至觀察者。比如說client執行一次寫操作,節點資料內容發生變化,操作返回後,而watch事件可能還在發往client的路上這種情況下,但ZooKeeper保證了一個順序:一個客戶端在收到watch事件之前,一定不會看到它設定過watch節點的變動。網路時延和其他因素可能會導致不同的客戶端看到watch和更新返回值的時間不同。但關鍵點是,從客戶端接收到的watch事件順序一定和ZooKeeper服務所看到的事件順序是一致的。

  •  

觀察者觀察的資料ZooKeeper中一個節點發生改變會有不同的方式。也就是,在zk服務端中,維護著兩個觀察者列表:資料觀察者、子節點觀察者。getData()exists()設定的是資料觀察者,getChildren()設定的是子節點觀察者。

① exists操作上的watch,在被監視的Znode建立刪除資料更新時被觸發。
 getData操作上的watch,在被監視的Znode刪除資料更新時被觸發。在被建立時不能被觸發,因為只有Znode一定存在,getData操作才會成功。
 getChildren操作上的watch,在被監視的Znode的子節點建立刪除,或是這個Znode自身刪除時被觸發。可以通過檢視watch事件型別來區分是Znode,還是他的子節點被刪除:NodeDelete表示Znode被刪除,NodeDeletedChanged表示子節點被刪除。

Zookeeper中的角色

» 領導者(leader),負責進行投票的發起和決議,更新系統狀態
  » 學習者(learner),包括跟隨者(follower)和觀察者(observer),follower用於接受客戶端請求並想客戶端返回結果,在選主過程中參與投票
  » Observer可以接受客戶端連線,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態,observer的目的是為了擴充套件系統,提高讀取速度
  » 客戶端(client),請求發起方

Zookeep節點資料操作流程

1.ClientFollwer發出一個寫的請求

2.Follwer把請求傳送給Leader

3.Leader接收到以後開始發起投票並通知Follwer進行投票

4.Follwer把投票結果傳送給Leader

5.Leader將結果彙總後如果需要寫入,則開始寫入同時把寫入操作通知給Leader,然後commit;

6.Follwer把請求結果返回給Client

 

• Follower主要有四個功能:
• 1. Leader傳送請求(PING訊息、REQUEST訊息、ACK訊息、REVALIDATE訊息);
• 2 .接收Leader訊息並進行處理;
• 3 .接收Client的請求,如果為寫請求,傳送給Leader進行投票;
• 4 .返回Client結果。
• Follower的訊息迴圈處理如下幾種來自Leader的訊息:
• 1 .PING訊息: 心跳訊息;
• 2 .PROPOSAL訊息:Leader發起的提案,要求Follower投票;
• 3 .COMMIT訊息:伺服器端最新一次提案的資訊;
• 4 .UPTODATE訊息:表明同步完成;
• 5 .REVALIDATE訊息:根據LeaderREVALIDATE結果,關閉待revalidatesession還是允許其接受訊息;
• 6 .SYNC訊息:返回SYNC結果到客戶端,這個訊息最初由客戶端發起,用來強制得到最新的更新