原文地址,轉載請註明出處: https://blog.csdn.net/qq_34021712/article/details/82870721 ©王賽超 html
https://blog.csdn.net/qq_34021712/article/category/9278741node
介紹
ZooKeeper(後面稱爲zk)是一種用於分佈式應用程序的分佈式開源協調服務。主要是用來解決分佈式應用中常常遇到的一些問題,假如你公司的項目仍是處於單機狀態,那可能用不到zk,一旦涉及到分佈式應用,不少問題均可以利用zk解決。
官網地址:http://zookeeper.apache.org/doc/current/zookeeperOver.htmlredis
1.設計目標
簡單
高可靠
有序
高性能
下面一一介紹:
簡單的數據模型算法
zk容許各分佈式應用經過一個共享的命名空間相互聯繫,該命名空間相似於一個標準的文件系統:由若干註冊了的數據節點構成(用zk的術語叫znode),這些節點相似於文件和目錄。與專爲存儲而設計的典型文件系統不一樣,zk數據保存在內存中,這意味着zk能夠實現高吞吐量和低延遲數量。數據庫
高可靠express
就像zk須要協調的分佈式系統同樣,它自己就是具備冗餘結構,它構建在一系列主機之上,構成zk服務的各服務器之間必須相互知道,它們維護着一個狀態信息的內存映像,以及在持久化存儲中維護着事務日誌和快照。只要大部分服務器正常工做,zk服務就能正常工做。客戶端鏈接到一臺zk服務器。客戶端維護這個TCP鏈接,經過這個鏈接,客戶端能夠發送請求、獲得應答,獲得監視事件以及發送心跳。若是這個鏈接斷了,客戶端能夠鏈接到另外一個zk服務器。
1.客戶端隨機鏈接集羣中任何一臺server
2.集羣內全部server基於Zab(ZooKeeper Atomic Broadcast)協議進 行通訊
3.集羣內部根據算法自動選舉出一個leader,負責向follower(其餘 server)廣播全部變化消息
4.集羣中每一個follower都和leader通訊
• Follower接收來自leader的全部變化消息,保存在本身內存
• Follower轉發來自客戶端的寫請求給leader
• 客戶端的讀請求會在follower端直接服務,無需轉發給leaderapache
zk集羣角色
Leader
①Leader服務器是zk集羣工做機制的核心.
②事務請求的惟一調度者和處理者,保證集羣事務請求處理的順序性.
Follower
①Follower服務器是zk集羣狀態的跟隨者.
②處理非事務請求,轉發事務請求給Leader服務器
③參與事務請求的proposal投票
④參與Leader選舉投票
Observer
Observer是一種新型的zk節點,Observer服務器只提供非事務服務.一般用於不影響集羣事務處理能力的前提下提高集羣的非事務的處理能力,Observer有另一個優點,由於它不參與投票,因此他們不屬於zk集羣的關鍵部位,即便他們Failed,或者從集羣中斷開,也不會影響集羣的可用性。服務器
有序性
zk給每次更新附加一個數字標籤,代表zk中的事務順序,後續操做能夠利用這個順序來完成更高層次的抽象功能,例如同步原語操做。網絡
高性能
zk特別適合於以讀爲主要負荷的場合。zk能夠運行在數千臺機器上,若是大部分操做爲讀,例如讀寫比例爲10:1,zk的效率會很高。session
下面瞭解一下數據模型的一些操做:
數據模型 與其操做
和文章剛開始講的簡單的數據模型同樣,zk提供的名稱空間很是相似於標準文件系統。名稱是由斜槓(/)分隔的路徑元素序列。zk名稱空間中的每一個節點都由路徑標識。
節點介紹
在zk中每一個命名空間(Namespace)被稱爲znode,每一個znode包含一個路徑和與之相關的元數據,以及繼承自該節點的孩子列表(臨時節點下面不能建立子節點),zk旨在存儲協調數據:狀態信息,配置,位置信息等,所以存儲在每一個節點的數據一般很小,在字節到千字節範圍內。
一個znode維護了一個屬性結構,該結構包括:版本號、ACL變動、時間戳。每次znode數據發生變化,版本號都會遞增,這樣客戶端的讀請求能夠基於版本號來檢索狀態相關數據。
每一個znode都有一個ACL,用來限制是否能夠訪問該znode。
在一個命名空間中,對znode上存儲的數據執行讀和寫請求操做都是原子的。
zk中有幾種節點類型
注意:節點類型在節點建立的時候就被肯定且不可改變
臨時節點(EPHEMERAL):臨時建立的,會話結束節點自動被刪除,也能夠手動刪除,臨時節點不能擁有子節點.
持久節點(PERSISTENT):建立後永久存在,除非主動刪除。
以上兩種節點爲Non-sequence節點,只有一個可建立成功,其它勻失敗。而且建立出的節點名稱與建立時指定的節點名徹底同樣.
臨時順序節點(EPHEMERAL_SEQUENTIAL):具備臨時節點特徵,可是它會有序列號。
持久順序節點(PERSISTENT_SEQUENTIAL):具備持久節點特徵,可是它會有序列號。
以上兩種節點爲sequence節點,建立出的節點名在指定的名稱以後帶有10位10進制數的序號。多個客戶端建立同一名稱的節點時,都能建立成功,只是序號不一樣
容器節點(CONTAINER):若是節點中最後一個子Znode被刪除,將會觸發刪除該Znode;
持久定時節點(PERSISTENT_WITH_TTL):客戶端斷開鏈接後不會自動刪除Znode,若是該Znode沒有子Znode且在給定TTL時間內無修改,該Znode將會被刪除;TTL單位是毫秒,必須大於0且小於或等於 EphemeralType.MAX_TTL
持久順序定時節點(PERSISTENT_SEQUENTIAL_WITH_TTL):同PERSISTENT_WITH_TTL,且Znode命名末尾自動添加遞增編號;
以上三種節點是在3.5.3-beta版中才有的
節點信息
每個Znode都有對應的stat結構,和文件系統相似。stat狀態主要包含下面的信息:
cZxid. 節點被建立時候的事務ID
mZxid 節點最後一次被修改時候的事務ID
pZxid 該節點的子節點最後一次被修改時的事務ID。子節點刪除或添加纔會影響pZxid
ctime 節點被建立的時間
mtime 節點被修改的世界
dataVersion 這個節點數據改變的次數
cversion 子節點被改變的次數
aclVersion 節點的ACL(訪問控制列表被改變的次數)
ephemeralOwner 建立該臨時節點的 session ID。若是是持久節點,設置爲0
dataLength 數據內容長度
numChildren 當前節點子節點的個數
可使用ls2和stat命令查看ZooKeeper節點下的信息。
節點的訪問控制(ACL)
zk提供了ACL來控制znode節點的訪問,只有符合了ACL控制,才能夠操做該節點,不然將沒法操做。
Zookeeper支持可配置的認證機制。它利用一個三元組來定義客戶端的訪問權限:
(scheme:expression, perms) 。其中:
Schema 表明權限控制模式,分別爲:
● World 任何人
● Auth 不須要ID
● Digest 用戶名和密碼方式的認證
● IP Address IP地址方式的認證
perms(權限),ZooKeeper支持以下權限
● CREATE: 建立子節點
● READ: 獲取子節點與自身節點的數據信息
● WRITE:在Znode節點上寫數據
● DELETE:刪除子節點
● ADMIN:設置ACL權限
注意:
Znode的Acl只是針對某個節點,不會做用到它的子節點上
任何鏈接到ZooKeeper的客戶端均可以使用exist操做,exist是不須要權限的。
zk能夠保證以下特性:
順序一致性
客戶端的更新順序與它們被髮送的順序一致。
原子性
更新操做要麼成功,要麼失敗,沒有第三種結果。
單系統映像
不管客戶端鏈接到哪個服務器,他都將看到相同的zk視圖。
可靠性
一旦一個更新操做被應用,那麼在客戶端再次更新以前,其值不會再改變。
實時性
zk保證客戶端將在一個時間間隔範圍內得到服務器的更新信息,或者服務器失效的信息。 但因爲網絡延時等緣由,zk不能保證兩個客戶端能同時獲得剛更新的數據,若是須要最新數據,應該在讀數據以前調用sync()接口。
Zookeeper Watch機制
zk支持監聽, 客戶端可以設置監聽znode節點. 當znode節點變動時可能觸發或者移除監聽.當監聽事件被觸發了,客戶端將會收到數據通知包,告訴客戶端節點數據被修改了. 同時若是當前客戶端和zk節點的鏈接被斷開了.客戶端將收到一個本地通知.
有以下的Watcher事件類型可能出現:
NodeChildrenChanged: zNode的子節點建立或刪除的時候
NodeCreated: 新的Znode節點被建立的時候
NodeDataChanged: Znode節點的數據改變了的時候
NodeDeleted: Znode節點被刪除的時候。
Watcher操做特色
主動推送 Watch被觸發時,由 zk 服務器主動將更新推送給客戶端,而不須要客戶端輪詢。
一次性 數據變化時,Watch 只會被觸發一次。若是客戶端想獲得後續更新的通知,必需要在 Watch 被觸發後從新註冊一個 Watch。
可見性 若是一個客戶端在讀請求中附帶 Watch,Watch 被觸發的同時再次讀取數據,客戶端在獲得 Watch 消息以前確定不可能看到更新後的數據。換句話說,更新通知先於更新結果。
順序性 若是多個更新觸發了多個 Watch ,那 Watch 被觸發的順序與更新順序一致。避免安裝大量watches偵聽在同一個節點
沒法保證跟蹤到每個變化
ZooKeeper Session
客戶端和server間採用長鏈接
鏈接創建後,server產生session ID(64位)返還 給客戶端
客戶端按期發送ping包來檢查和保持和server的 鏈接
一旦session結束或超時,全部ephemeral節點會 被刪除
客戶端可根據狀況設置合適的session超時時間
客戶端可以異步接收來自服務端的Watcher事件通知
ZooKeeper典型8大應用場景及對應的特性:
配置管理服務
例如噹噹的configtoolkit配置中心,就是將配置信息放到了zk上,假如你有20個節點,須要修改配置文件的時候,你總不能一個節點一個節點去更改吧 那假若有100個節點呢?在分佈式系統中,有不少實例中的大多數配置項是相同的(好比數據庫鏈接等),須要改變配置項,若是有zk的話,不須要在每一個實例去修改。全部實例在啓動時,都回去zk拉取節點信息,當節點信息修改的時候會通知到每個實例,某些配置項也能夠達到熱配置的效果。
集羣管理(Master選舉)
在分佈式的集羣中,常常會因爲各類緣由,好比硬件故障,軟件故障,網絡問題,有些節點會進進出出。有新的節點加入進來,也有老的節點退出集羣。這個時候,集羣中其餘機器須要感知到這種變化,而後根據這種變化作出對應的決策。好比咱們是一個分佈式存儲系統,有一箇中央控制節點負責存儲的分配,當有新的存儲進來的時候咱們要根據如今集羣目前的狀態來分配存儲節點。這個時候咱們就須要動態感知到集羣目前的狀態。還有,好比一個分佈式的SOA架構中,服務是一個集羣提供的,當消費者訪問某個服務時,就須要採用某種機制發現如今有哪些節點能夠提供該服務(這也稱之爲服務發現,好比Alibaba開源的SOA框架Dubbo就採用了zk做爲服務發現的底層機制)。還有開源的Kafka隊列就採用了zk做爲Cosnumer的上下線管理。
還有一個場景:集羣選master,一旦master掛掉可以立刻能從slave中選出一個master,這個實現和上面實現同樣。
命名服務
命名服務就是指經過指定的名字來獲取資源或者服務的地址。zk會在本身的文件系統上(樹結構的文件系統)建立一個以路徑爲名稱的節點,它能夠指向提供的服務的地址,遠程對象等。分佈式服務框架Dubbo中使用ZooKeeper來做爲其命名服務,維護全局的服務地址列表。
分佈式計數器
在分佈式環境下,獲取惟一id,功能和redis自增返回值同樣,指定一個Zookeeper數據節點做爲計數器,多個應用實例在分佈式鎖的控制下,經過更新該數據節點的內容來實現計數功能。
分佈式協調通知
說分佈式協調通知就有點廣了,上面所說的配置服務和集羣管理就是用到了分佈式協調通知,分佈式協調/通知服務是分佈式系統中不可缺乏的一個環節,是將不一樣的分佈式組件有機結合起來的關鍵所在。
利用zk中特有的Watcher註冊與異步通知機制,可以很好的實現分佈式環境下不一樣機器,甚至是不一樣系統之間的協調與通知,從而實現對數據變動的實時處理。
利用zk的心跳機制和臨時節點特性,可讓不一樣的機器都在zk的一個指定節點下建立臨時子節點,不一樣的機器之間能夠根據這個臨時節點來判斷對應的客戶端機器是否存活。經過這種方式,檢測系統和被檢測系統之間並不須要直接相關聯,而是經過zk上的某個節點進行關聯,大大減小了系統耦合。
發佈訂閱
發佈/訂閱模式是一對多的關係,多個訂閱者對象同時監聽某一主題對象,這個主題對象在自身狀態發生變化時會通知全部的訂閱者對象。使它們能自動的更新本身的狀態。發佈/訂閱可使得發佈方和訂閱方獨立封裝、獨立改變。當一個對象的改變須要同時改變其餘對象,並且它不知道具體有多少對象須要改變時可使用發佈/訂閱模式。發佈/訂閱模式在分佈式系統中的典型應用有配置管理和服務發現、註冊。
配置管理是指若是集羣中的機器擁有某些相同的配置而且這些配置信息須要動態的改變,咱們可使用發佈/訂閱模式把配置作統一集中管理,讓這些機器格子各自訂閱配置信息的改變,當配置發生改變時,這些機器就能夠獲得通知並更新爲最新的配置。
服務發現、註冊是指對集羣中的服務上下線作統一管理。每一個工做服務器均可以做爲數據的發佈方向集羣註冊本身的基本信息,而讓某些監控服務器做爲訂閱方,訂閱工做服務器的基本信息,當工做服務器的基本信息發生改變如上下線、服務器角色或服務範圍變動,監控服務器能夠獲得通知並響應這些變化。
分佈式鎖
每一個客戶端對某個方法加鎖時,在zk上的與該方法對應的指定節點的目錄下,生成一個惟一的瞬時有序節點。 判斷是否獲取鎖的方式很簡單,只須要判斷本身建立的子節點是否爲當前子節點列表中序號最小的子節點,若是是則認爲得到鎖,不然監聽/lock的子節點變動消息,得到子節點變動通知後重復此步驟直至得到鎖。
隊列管理zk隊列不太適合要求高性能的場合,能夠考慮在數據量不大的狀況下使用。畢竟引進一個消息中間件會增長系統的複雜性和運維的壓力。固然了,首先已有項目中要使用zk。使用zk實現先進先出隊列就是在特定的目錄下建立PERSISTENT_EQUENTIAL(永久、序列化)節點,建立成功時Watcher通知等待的隊列,隊列刪除序列號最小的節點用以消費。此場景下zk的znode用於消息存儲,znode存儲的數據就是消息隊列中的消息內容,SEQUENTIAL序列號就是消息的編號,按序取出便可。因爲建立的節點是持久化的,因此沒必要擔憂隊列消息的丟失問題。SEQUENTIAL:一旦節點被標記上SEQUENTIAL這個屬性,那麼在這個節點被建立的時候,ZooKeeper 就會自動在其節點後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。————————————————版權聲明:本文爲CSDN博主「這個名字想了好久」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/qq_34021712/article/details/82870721