zookeeper數據存儲
1. zookeeper
客戶端的Watcher
String就是節點的path,有三大類。
dataWatches:數據watcher
existWatches:節點是否存在的watcher
childWatches:節點的子節點個數變化,包括:0->1,1->2等等,只要數量變化就觸發。
對於zk的watcher機制,有幾個疑問?
三、ZK的通信協議
分兩類:請求和響應協議。是基於TCP/IP的應用層協議,其實就是規定了應用層報文的格式,以及每個欄位的含義。客戶端和服務端雙方都遵守這種約定,脫離了ZK,其他框架是無法識別這種通信協議的。
請求和響應報文格式,網上搜一下一大堆。這里不再贅述
那麼回到什麼是分布式協調呢?我們就以RPC這種場景來說:
比如我們可以理解上面的圖,一半client是service角色,一半client是consumer角色,然後zk提供了這些client之間的協調 -- 充當consumer角色的client必須依賴於充當service角色提供的服務,這可不就是分布式協調的一種嘛(協調其中一半的client依賴另一半)。當然我們可以繼續擴展:分布式配置中心Disconf,有個client它的角色可以是管理員(配置員),它是一個進程。它向zk某一個節點配置了XX數據,然後其他所有client同時收到最新配置。這可不就是另外一種協調了嘛(其他client依賴這個配置的值執行業務)。
ZooKeeper 是一個典型的分布式數據一致性解決方案,分布式應用程序可以基於 ZooKeeper 實現諸如數據發布/訂閱、負載均衡、命名服務、分布式協調/通知、集群管理、Master 選舉、分布式鎖和分布式隊列等功能
乍一看這個定義挺抽象的,一時半會沒理解。其實舉個例子就容易理解的多,比如你有個資源,我們先簡單把該資源當做一個本地文件或本地電影。你為了保證該資源的可靠性,你需要把該資源到3台機器上。那麼這三個資源,在互聯網上就會有三個url地址:機器1/xxx/xxx/xxx.pdf,機器2/xxx/xxx/xxx.pdf,機器3/xxx/xxx/xxx.pdf。請求方為了訪問該資源,肯定不會把這三個地址硬編碼到自己本地,這樣不易拓展。所以這個時候,就需要一個統一命名服務來封裝該資源的三個真實地址,對外只提供一個地址並且永遠可以不變。那麼這個統一命名服務,我們當然可以用http協議來實現,也可以用zk協議(ZAB協議)來實現。
現在理解了上面的內容,那麼我們就容易拓展這個資源的定義了。上面所說的資源,我們可以拓展為一個服務 xxx.xxx.xxx.UserService,該服務的提供方可以有很多個,但是為了封裝真實提供方,我們只能對外暴露一個地址那就是xxx.xxx.xxx.UserService。是不是很熟悉?Dubbo的ZK注冊中心,就是這么乾的。
理解定義我們就不說了,這個很好理解。實際案例咱們可以參考Dubbo的ZK,提供者發布或修改服務真實地址後,消費者可以實時收到變化的通知,然後再去ZK拉取最新數據。這可不就是ZK的發布與訂閱嘛,通過Listener觀察者模式來實現。應用場景很多:RPC服務發現,配置中心的配置分發等等。
所謂集群管理無在乎兩點:是否有機器退出和加入、選舉 Master。
不就是ZK的發布訂閱嘛,沒啥好說的。
這里的maser選舉,可不是ZK內部的master選舉(兩者相差十萬八千里)。這里的master選舉,是指業務調用方,屬於client角色的進程,進行選舉。
業務master選舉其實很簡單,完全沒必要像ZK內部選舉那樣,還要實現一套可靠的選舉演算法(paxos演算法包含了一個提案選舉,paxos演算法可不止一個選舉演算法)。ZK本身提供了一個可靠創建唯一節點的API介面,這個介面保證了並發調用只會有一個成功。那麼業務master選舉,是不是可以轉化為多個業務進程並發調用該API介面,誰創建唯一節點成功了,誰就是master了,其他進程就是slave。怎麼感覺這么像分布式鎖的實現呢?除了少了釋放鎖的通知操作。。。
軟負載均衡也沒啥好說的,就是注冊與發現的變種,或者說發布與訂閱的變種。獲取統一命名服務的所有提供者列表,然後通過負載均衡演算法在這一堆列表中選擇一個,策略可以是隨機選擇,輪訓選擇,Hash一致性選擇等等。。。Dubbo的負債均衡是實現在消費者調用邏輯裡面的,並不在獲取列表介面裡面,ZK不做負載均衡,基於ZK的應用可以做。
和上面的數據發布與訂閱 一模一樣 ,不在贅述。
和上面說的Master選舉很像,都是一堆client角色的業務調用方,調用創建某唯一節點的API。誰創建成功,誰就拿鎖。只不過ZK的底層實現是嚴格按照順序來的,所以必然是ZK接收請求的時候,誰第一個誰拿鎖。注意可不是client誰先請求誰拿鎖。client請求還要經過網路,同時請求是沒法確定哪個client先到達的。
但是光創建唯一節點成功還不叫鎖,鎖天然包含了兩個功能:可重入和釋放鎖喚醒其他等待的client節點。可重入ZK是實現不了,需要業務方自己實現。釋放鎖的喚醒ZK是通過Listener的通知喚醒的。
我們看下上面的所有應用場景,其實本質上都是調用zk的兩個最核心的介面:創建節點和監聽節點變化。
ZooKeeper 將數據保存在內存中,這也就保證了高吞吐量和低延遲 (但是內存限制了能夠存儲的容量不太大,此限制也是保持 znode 中存儲的數據量較小的進一步原因)。ZK集群加機器可不能增加內存,為啥呢?因為ZK集群裡面的所有數據,都是每台機器保存一份副本。整個集群內存最小的機器,決定整個集群的內存大小。
ZooKeeper 是高性能的。在「讀」多於「寫」的應用程序中尤其的高性能 ,因為「寫」會導致所有的伺服器間同步狀態。(「讀」多於「寫」是協調服務的典型場景。)
ZooKeeper 底層其實只提供了兩個功能:
2. zookeeper跟php結合做服務配置的處理 該怎麼處理
Zookper: 一種分布式應用的協作服務
Zookper是一種分布式的,開源的,應用於分布式應用的協作服務。它提供了一些簡單的操作,使得分布式應用可以基於這些介面實現諸如同步、配置維護和分集群或者命名的服務。Zookper很容易編程接入,它使用了一個和文件樹結構相似的數據模型。可以使用Java或者C來進行編程接入。
眾所周知,分布式的系統協作服務很難有讓人滿意的產品。這些協作服務產品很容易陷入一些諸如競爭選擇條件或者死鎖的陷阱中。Zookper的目的就是將分布式服務不再需要由於協作沖突而另外實現協作服務。
設計目標 Zookeeper是簡易的
Zookeeper通過一種和文件系統很像的層級命名空間來讓分布式進程互相協同工作。這些命名空間由一系列數據寄存器組成,我們也叫這些數據寄存器為znodes。這些znodes就有點像是文件系統中的文件和文件夾。和文件系統不一樣的是,文件系統的文件是存儲在存儲區上的,而zookeeper的數據是存儲在內存上的。同時,這就意味著zookeeper有著高吞吐和低延遲。
Zookeeper實現了高性能,高可靠性,和有序的訪問。高性能保證了zookeeper能應用在大型的分布式系統上。高可靠性保證它不會由於單一節點的故障而造成任何問題。有序的訪問能保證客戶端可以實現較為復雜的同步操作。
Zookeeper是可重用的
ZooKeeper Service
image
組成Zookeeper的各個伺服器必須要能相互通信。他們在內存中保存了伺服器狀態,也保存了操作的日誌,並且持久化快照。只要大多數的伺服器是可用的,那麼Zookeeper就是可用的。
客戶端連接到一個Zookeeper伺服器,並且維持TCP連接。並且發送請求,獲取回復,獲取事件,並且發送連接信號。如果這個TCP連接斷掉了,那麼客戶端可以連接另外一個伺服器。
Zookeeper是有序的
Zookeeper使用數字來對每一個更新進行標記。這樣能保證Zookeeper交互的有序。後續的操作可以根據這個順序實現諸如同步操作這樣更高更抽象的服務。
Zookeeper是高效的
Zookeeper的高效更表現在以讀為主的系統上。Zookeeper可以在千台伺服器組成的讀寫比例大約為10:1的分布系統上表現優異。
數據結構和分等級的命名空間
Zookeeper的命名空間的結構和文件系統很像。一個名字和文件一樣使用/的路徑表現,zookeeper的每個節點都是被路徑唯一標識
ZooKeeper's Hierarchical Namespace
image
實現
下圖顯示了ZooKeeper服務的高級組件服務。除了請求處理器,Zookeeper伺服器組的每個伺服器復制他們自己的每個組件。
ZooKeeper Components
image
replicated database是一個存儲在內存中的包含整個數據樹的結構。所有的更新操作都做日誌到硬碟上了。並且寫操作在作用在資料庫的時候會序列化存儲到硬碟上。
每個ZooKeeper伺服器都連接了許多個客戶端。客戶端連接到一個伺服器來提交請求。
3. Zookeeper深入原理
Zookeeper 的視圖結構是一個樹形結構,樹上的每個節點稱之為數據節點(即 ZNode),每個ZNode 上都可以保存數據,同時還可以掛載子節點。並且Zookeeper的根節點為 "/"。
在 Zookeeper 中,每個數據節點都是有生命周期的,其生命周期的長短取決於數據節點的節點類型。在 Zookeeper 中有如下幾類節點:
每個數據節點中除了存儲了數據內容之外,還存儲了數據節點本身的一些狀態信息(State)。
在Zookeeper 中,事務是指能夠改變 Zookeeper 伺服器狀態的操作,我們也稱之為事務操作或更新操作,一般包括數據節點創建與刪除、數據節點內容更新和客戶端會話創建與失效等操作。對於每一個事務請求,Zookeeper 都會為其分配一個全局唯一的事務ID,用 ZXID 來表示,通常是一個 64 位的數字。每一個 ZXID 對應一次更新操作,從這些 ZXID 中可以間接地識別出 Zookeeper 處理這些更新操作請求的全局順序。
ZXID 是一個 64 位的數字,其中低 32 位可以看作是一個簡單的單調遞增的計數器,針對客戶端的每一個事務請求,Leader 伺服器在產生一個新的事務 Proposal 的時候,都會對該計數器進行加 1 操作;而高 32 位則代表了 Leader 周期 epoch 的編號,每當選舉產生一個新的 Leader 伺服器,就會從這個 Leader 伺服器上取出其本地日誌中最大事務 Proposal 的 ZXID,並從該 ZXID 中解析出對應的 epoch 值,然後再對其進行加 1 操作,之後就會以此編號作為新的 epoch,並將低 32 位置 0 來開始生成新的 ZXID。
Zookeeper 中為數據節點引入了版本的概念,每個數據節點都具有三種類型的版本信息(在上面的狀態信息中已經介紹了三種版本信息代表的意思),對數據節點的任何更新操作都會引起版本號的變化。其中我們以 dataVersion 為例來說明。在一個數據節點被創建完畢之後,節點的dataVersion 值是 0,表示的含義是 」當前節點自從創建之後,被更新過 0 次「。如果現在對該節點的數據內容進行更新操作,那麼隨後,dataVersion 的值就會變成 1。即表示的是對數據節點的數據內容的變更次數。
版本的作用是用來實現樂觀鎖機制中的 「寫入校驗」 的。例如,當要修改數據節點的數據內容時,帶上版本號,如果數據節點的版本號與傳入的版本號相等,就進行修改,否則修改失敗。
Zookeeper 提供了分布式數據的發布/訂閱功能。一個典型的發布/訂閱模型系統定義了一種一對多的訂閱關系,能夠讓多個訂閱者同時監聽某一個主題對象,當這個主題對象自身狀態變化時,會通知所有訂閱者,使它們能夠做出相應的處理。在 Zookeeper 中,引入了 Watcher 機制來實現這種分布式的通知功能。Zookeeper 允許客戶端向服務端注冊一個 Watcher 監聽,當服務端的一些指定事件觸發了這個 Watcher,那麼就會向指定客戶端發送一個事件通知來實現分布式的通知功能。
從上圖可以看出 Zookeeper 的 Watcher 機制主要包括客戶端線程、客戶端WatchMananger 和 Zookeeper 伺服器三部分。在具體工作流程上,簡單地講,客戶端在向 Zookeeper 伺服器注冊 Watcher 的同時,會將 Watcher 對象存儲在客戶端的 WatchMananger 中。當 Zookeeper 伺服器端觸發 Watcher 事件後,會向客戶端發送通知,客戶端線程從 WatchManager 中取出對應的 Watcher 對象來執行回調邏輯。
Watcher是一個介面,任何實現了Watcher介面的類就是一個新的Watcher。Watcher內部包含了兩個枚舉類:KeeperState、EventType
注 :客戶端接收到的相關事件通知中只包含狀態及類型等信息,不包括節點變化前後的具體內容,變化前的數據需業務自身存儲,變化後的數據需調用get等方法重新獲取;
上面講到zookeeper客戶端連接的狀態和zookeeper對znode節點監聽的事件類型,下面我們來講解如何建立zookeeper的watcher監聽。在zookeeper中採用zk.getChildren(path, watch)、zk.exists(path, watch)、zk.getData(path, watcher, stat)這樣的方式為某個znode注冊監聽。
下表以node-x節點為例,說明調用的注冊方法和可監聽事件間的關系:
Zookeeper 中提供了一套完善的 ACL(Access Control List)許可權控制機制來保障數據的安全。
ACL 由三部分組成,分別是:許可權模式(Scheme)、授權對象(ID)和許可權(Permission),通常使用「scheme: id:permission」來標識一個有效的ACL 信息。下面分別介紹:
1.7.4、ACL 超級管理員
zookeeper的許可權管理模式有一種叫做super,該模式提供一個超管可以方便的訪問任何許可權的節點
假設這個超管是:super:admin,需要先為超管生成密碼的密文
那麼打開zookeeper目錄下的/bin/zkServer.sh伺服器腳本文件,找到如下一行:
這就是腳本中啟動zookeeper的命令,默認只有以上兩個配置項,我們需要加一個超管的配置項
那麼修改以後這條完整命令變成了
之後啟動zookeeper,輸入如下命令添加許可權
在伺服器集群初始化階段,我們以 3 台機器組成的伺服器集群為例,當有一台伺服器server1 啟動的時候,它是無法進行 Leader 選舉的,當第二台機器 server2 也啟動時,此時這兩台伺服器已經能夠進行互相通信,每台機器都試圖找到一個 Leader,於是便進入了 Leader 選舉流程。
在zookeeper運行期間,leader與非leader伺服器各司其職,即便當有非leader伺服器宕機或新加入,此時也不會影響leader,但是一旦leader伺服器掛了,那麼整個集群將暫停對外服務,進入新一輪leader選舉,其過程和啟動時期的Leader選舉過程基本一致。
假設正在運行的有server1、server2、server3三台伺服器,當前leader是server2,若某一時刻leader掛了,此時便開始Leader選舉。選舉過程如下:
observer角色特點:
為了使用observer角色,在任何想變成observer角色的配置文件中加入如下配置:
並在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
4. zkparking資料庫配置程序
摘要 這邊給您查詢分析到每台機器的應用程序都需要連接資料庫,而資料庫的配置信息(連接信息),這時候放在機器本地的話不方面(機器多,需要一個個改配置信息),這就用到Zookeeper,把資料庫的配置信息放到配置中心,利用Zookeeper節點可以存儲數據的特性,然後各台機器可以使用JavaAPI去獲取Zookeeper中資料庫的配置信息。每一個應用都在Zookeeper節點注冊監聽器,一旦節點信息改變,各台機器就獲取信息,使用最新的信息連接資料庫,這樣優點一是方便了管理(只放置一份數據在配置中心,沒必要放到多個機器上去),二是一旦配置改了,就做一個發布的動作即可。