zookeeper原理及應用

ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是GoogleChubby一個開源的實現。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個劃分維度:按節點是否可持久化存儲,分爲持久節點與臨時節點;按節點序號是否可順序遞增(相似mysqlauto_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...)架構

臨時節點 (clientzk斷開鏈接後,節點自動刪除)併發

臨時順序節點

  • 事件監聽
    • Created event (節點建立事件)
    • Deleted event (節點刪除事件)
    • Changed event (節點的數據變化事件) -zkClient.subscribeChildChanges(); //訂閱子節點的變化
    • zkClient.subscribeDataChanges();//訂閱某節點的數據變化(包括數據被刪除)事件
    • zkClient.subscribeStateChanges();//訂單狀態變化(狀態包括:鏈接,斷開,認證失敗等等)

以上爲經常使用事件,其它事件請參考官方文檔。實際使用中,不多用原生寫法來監聽事件,而是藉助一些第三方的開源zk客戶端,好比zkClient來監聽事件。

  • ACL(Access Control List)權限控制

    • 每一個節點有5種操做權限:Create、Read、Write、Delete、Admin 簡稱crwda。其中:Delete是指對子節點是否具備刪除權限,其它4種權限指對自身節點的操做權限。
    • 身份認證方式:world:默認方式,無限制,全世界均能訪問。auth: 在上下文中添加受權用戶。digest: 用戶名/密碼認證ip: ip地址認證

應用場景

  • 應用場景1:分佈式配置

要點:配置信息保存在dbzk中(保險起見,數據安全性更高),弄一個後臺管理界面,對配置修改後,先保存到db,而後同步寫入zk的節點中。應用啓動時,先連到zk上讀取節點中的配置,同時監聽節點的數據變化,當配置變化時,獲得實時通知。

  • 應用場景2:消除單點故障(Single Point of Failure,SPOF)
└── ./OrderNoService
        ├── A0000001
                10.0.0.1:8001
        └── A0000002
                10.0.0.2:8001
複製代碼

多個服務實例,啓動時在zk上臨時順序節點,服務的調用方約定取最小節點爲Master,當master掛掉後,節點自動刪除,調用方獲得事件通知,取新的最小節點來調用(至關於slave提高爲master)

  • 應用場景3:去中心化

上圖中,左邊爲傳統中心化的架構,缺點是每次有新的服務實例加入或下線,都要調整nginx中心節點的配置(不論是人工,仍是藉助工具自動),不利於雲時代的動態彈性調整,並且總體的可用性強依賴於中心節點,一旦中心節點(中心集羣)全掛掉,系統就不可用了。

  • 應用場景4:分佈式鎖
Order
    └── 3456890
        ├── 000001
        ├── 000002
        └── 000003
複製代碼

原理:以多個程序運行實例同時在處理訂單3456890爲例,每一個程序運行實例處理前,建立一個臨時順序節點,而後檢查本身建立的節點是否爲最小,若是不是,代表沒搶到鎖,若是是,表示搶到了鎖,搶到鎖的程序處理完之後,刪除該節點表示釋放鎖。同時,其它處於等候狀態的程序,爲了實時獲得鎖的釋放通知,均監聽父節點Order/3456890的子節點變化,發現子節點變化時,重複剛纔的檢測過程,直到本身建立的節點變成最小爲止。 與redis SETNX之類的分佈式鎖相比,zk的分佈式鎖,還能實現解決Top N之類的有限資源競爭問題(相似併發中的信號量)。好比:一堆程序要打印,可是隻有2臺打印機(或者打印隊列的長度只有2,最多同時只能容許2個程序提交打印任務), 相似剛纔的思路 ,能夠檢測最小的前2個節點,只有建立最小前2個節點的程序,才認爲是拿到了信號,容許提交打印任務。

  • 應用場景5:分佈式隊列
Queue
    └── Queue1
        ├── 000001
        ├── 000002
        └── 000003
複製代碼

如上圖,建立Queue/Queue1作爲一個隊列(或Topic),而後每建立一個順序節點,視爲一條消息(節點存儲的數據即爲消息內容),生產者每次建立一個新節點,作爲消息發送,消費者監聽Queue1的子節點變化(或定時輪詢),每次取最小節點當作消費消息,處理完後,刪除該節點。至關於實現了一個FIFO(先進先出)的隊列。 注:zk框架強制的是CP(一致性),而非專爲高併發、高性能場景設計的,若是在高併發,qps很高的狀況下,分佈式隊列需酌情考慮。

  • 應用場景7:生成分佈式惟一id
Order
      └── OrderId
        ├── 000001
        ├── 000002
        └── 000003
複製代碼

思路:每次要生成一個新Id時,建立一個持久順序節點,建立操做返回的節點序號,即爲新Id,而後把比本身節點小的刪除便可。

終篇

目前不少開源項目,幾乎都是或多或少依賴zookeeper,好比:dubbo,disconf,kafka,...

分佈式環境中,zk能用於什麼場景,基本上取決於開發人員的想象力!

相關文章
相關標籤/搜索