ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google
的Chubby
一個開源的實現。node
Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination.
mysql
ZooKeeper以Fast Paxos
(帕克索斯)算法爲基礎,讓集羣中的每一個zk實例數據保持一致。通常部署集羣,機器數設置爲奇數個,更容易知足>N/2的投票條件。nginx
/
├── app1
│ ├── p_1
│ ├── p_2
│ └── p_3
└── app2
複製代碼
相似操做系統文件夾的樹型模型,與文件夾的區別在於,每一個節點上可存儲數據(不超過
1M
),每一個節點上的數據可帶版本號。redis
zNode
節點類型2
個劃分維度:按節點是否可持久化存儲,分爲持久節點與臨時節點;按節點序號是否可順序遞增(相似mysql
的auto_increment
),分爲順序節點及非順序節點,算法
注:3.6.0版本之後,還新增了Container Nodes
(容器節點),該節點的特色是,若是其下的全部子節點都被刪除,該節點也會在未來某個時間被刪除。sql
ZooKeeper has the notion of container nodes. Container nodes are special purpose nodes useful for recipes such as leader, lock, etc. When the last child of a container is deleted, the container becomes a candidate to be deleted by the server at some point in the future.
安全
持久節點
(client
建立持久節點後,就算與zk
斷開,節點仍然保存在zk
中)
bash持久順序節點
(eg: /order/quartz/wm000001 , /order/quartz/wm000002, /order/quartz/wm000003...)
架構臨時節點
(client
與zk
斷開鏈接後,節點自動刪除)
併發臨時順序節點
Created event
(節點建立事件)Deleted event
(節點刪除事件)Changed event
(節點的數據變化事件) -zkClient.subscribeChildChanges();
//訂閱子節點的變化zkClient.subscribeDataChanges();
//訂閱某節點的數據變化(包括數據被刪除)事件zkClient.subscribeStateChanges();
//訂單狀態變化(狀態包括:鏈接,斷開,認證失敗等等)以上爲經常使用事件,其它事件請參考官方文檔。實際使用中,不多用原生寫法來監聽事件,而是藉助一些第三方的開源zk客戶端,好比zkClient來監聽事件。
ACL(Access Control List)
權限控制
Create、Read、Write、Delete、Admin
簡稱crwda
。其中:Delete
是指對子節點是否具備刪除權限,其它4種權限指對自身節點的操做權限。world:
默認方式,無限制,全世界均能訪問。auth:
在上下文中添加受權用戶。digest:
用戶名/密碼認證ip: ip
地址認證要點:配置信息保存在
db
與zk
中(保險起見,數據安全性更高),弄一個後臺管理界面,對配置修改後,先保存到db
,而後同步寫入zk
的節點中。應用啓動時,先連到zk
上讀取節點中的配置,同時監聽節點的數據變化,當配置變化時,獲得實時通知。
(Single Point of Failure,SPOF)
└── ./OrderNoService
├── A0000001
10.0.0.1:8001
└── A0000002
10.0.0.2:8001
複製代碼
多個服務實例,啓動時在
zk
上臨時順序節點,服務的調用方約定取最小節點爲Master
,當master
掛掉後,節點自動刪除,調用方獲得事件通知,取新的最小節點來調用(
至關於slave
提高爲master)
上圖中,左邊爲傳統中心化的架構,缺點是每次有新的服務實例加入或下線,都要調整
nginx
中心節點的配置(
不論是人工,仍是藉助工具自動)
,不利於雲時代的動態彈性調整,並且總體的可用性強依賴於中心節點,一旦中心節點(
中心集羣)
全掛掉,系統就不可用了。
Order
└── 3456890
├── 000001
├── 000002
└── 000003
複製代碼
原理:以多個程序運行實例同時在處理訂單
3456890
爲例,每一個程序運行實例處理前,建立一個臨時順序節點,而後檢查本身建立的節點是否爲最小,若是不是,代表沒搶到鎖,若是是,表示搶到了鎖,搶到鎖的程序處理完之後,刪除該節點表示釋放鎖。同時,其它處於等候狀態的程序,爲了實時獲得鎖的釋放通知,均監聽父節點Order/3456890
的子節點變化,發現子節點變化時,重複剛纔的檢測過程,直到本身建立的節點變成最小爲止。 與redis SETNX
之類的分佈式鎖相比,zk
的分佈式鎖,還能實現解決Top N
之類的有限資源競爭問題(相似併發中的信號量)。好比:一堆程序要打印,可是隻有2臺打印機(或者打印隊列的長度只有2,最多同時只能容許2個程序提交打印任務), 相似剛纔的思路 ,能夠檢測最小的前2個節點,只有建立最小前2個節點的程序,才認爲是拿到了信號,容許提交打印任務。
Queue
└── Queue1
├── 000001
├── 000002
└── 000003
複製代碼
如上圖,建立
Queue/Queue1
作爲一個隊列(或Topic
),而後每建立一個順序節點,視爲一條消息(節點存儲的數據即爲消息內容),生產者每次建立一個新節點,作爲消息發送,消費者監聽Queue1
的子節點變化(或定時輪詢),每次取最小節點當作消費消息,處理完後,刪除該節點。至關於實現了一個FIFO
(先進先出)的隊列。 注:zk
框架強制的是CP
(一致性),而非專爲高併發、高性能場景設計的,若是在高併發,qps
很高的狀況下,分佈式隊列需酌情考慮。
id
Order
└── OrderId
├── 000001
├── 000002
└── 000003
複製代碼
思路:每次要生成一個新
Id
時,建立一個持久順序節點,建立操做返回的節點序號,即爲新Id
,而後把比本身節點小的刪除便可。
目前不少開源項目,幾乎都是或多或少依賴
zookeeper
,好比:dubbo,disconf,kafka,...
分佈式環境中,
zk
能用於什麼場景,基本上取決於開發人員的想象力!