一、Zookeeper介紹
Zookeeper是一個典型的釋出/訂閱模式的分布式資料管理與協調架構,開發人員可以使用它來進行分布式資料的釋出與訂閱,通過對Zookeeper中豐富的資料節點類型進行交叉使用,配合Watcher事件通知機制,可以非常方面地建構一系列分布式應用都會涉及到的核心功能,如資料釋出/訂閱、負載均衡、命名服務、分布式協調/通知、叢集管理、Master選舉、分布式鎖和分布式隊列等。
二、資料釋出/訂閱
釋出者将資料釋出到Zookeeper的一個或一系列的節點上,供訂閱者進行資料訂閱,進而達到動态擷取資料的目的,實作配置資訊的集中式管理和資料的動态更新。一般分為推(Push)模式和拉(Pull)模式。在推模式中,服務端主動将資料發送诶所有訂閱的用戶端,而拉模式則由用戶端主動發起請求擷取最新的資料。
在平常應用系統中,系統需要使用一些通用的配置資訊,例如機器清單資訊、資料庫配置等等,這些配置資訊通常具備以下三個特性:
- 資料量比較小
- 資料内容在運作時會動态的變化
- 叢集中各機器共享,配置一緻
三、負載均衡
通常在使用過程中,在Zookeeper上建立一個節點進行域名配置,如下圖
每一個應用都可以建立一個屬于自己的節點作為域名配置的根節點,然後将自己的域名配置行去,到時候,根據域名就可以找到這台伺服器對應的IP。
四、命名服務
命名服務是分布式系統中比較常見的一類場景,被命名為實體通常可以是叢集中的機器,提供的服務位址或者遠端對象等--這些都可以統稱它們我名字,較為常見的是分布式服務架構(RPC、RMI)中的服務位址清單,通過指令服務,用戶端就能夠根據這些指定的名字來擷取資源實體、伺服器資訊等。
通過調用Zookeeper節點建立API可以建立一個順序節點,并且在該API的傳回值中會傳回目前這個節點的完整名字,利用這個特性,就可以額借助Zookeeper來生成全局的唯一ID。
五、分布式協調通知
分布式協調/通知服務是分布式系統中不可缺少的一個環節,是将不同的分布式元件連接配接起來的關鍵。而對于一個在多台機器上部署的系統來說,通常需要一個協調者來控制整個系統的運作流程,例如分布式事務的處理,機器間的互相協調等。引入這樣的一個協調者,可以大大的減少系統之間的耦合性,能夠顯著的提高系統的可擴充性。
Zookeeper中的Watcher注冊和異步通知機制,能夠很好實作分布式環境下的不同機器,甚至是不同系統之間的協調通知,進而實作對資料變更的實時處理。就與Zookeeper實作分布式協調和通知功能,通常的做法是不同的用戶端都對Zookeeper上的同一個資料節點進行Watcher注冊,監聽資料節點的變化,如果節點資料發生變化,那麼所有訂閱的用戶端都可以接收到Watcher通知,并作出相應的處理。
六、叢集管理
包括叢集監控和叢集控制,前者側重于對于叢集實時運作狀态采集,後者則是對于叢集進行操作和控制。
在叢集中,機器完成注冊和任務分發之後,還要考慮這些機器随時都有挂掉的可能性,針對這種情況,需要一個收集器的裝填彙報機制,每一台機器在Zookeeper上建立一個自己的節點之後,還需要再子節點上建立一個自己的狀态節點,定時的向臨時節點寫入自己的狀态資訊,也就是一個心跳檢測機制。
七、Master選舉
Master選舉時一個分布式系統中非常常見的場景,分布式最核心的特性就是能夠将具有獨立計算能力的系統單元部署在不同的機器上,構成一個完整的分布式系統。
在分布式的系統中,Master通常用來協調叢集中的其他系統單元,具有對分布式系統狀态的決定權。例如:在一些讀寫分離的系統中,用戶端的寫請求往往是由Master來處理的,而在另外的一些場景中,Master常常負責一些複雜的邏輯,并将這些處理結果同步給系統的其他單元。
八、分布式鎖
分布式鎖是控制系統之間同步通路共享資源的一種方式。如果不同的系統或者同一個系統的不同主機之間共享了一個或者一組資源,那麼通路這些資源的時候,往往需要通過一些互斥的手段來通路之間的幹擾,一保證一緻性,這種情況下就需要使用分布式鎖。Zookeeper的分布式鎖分為兩種,排他鎖和共享鎖。
排他鎖(Exclusive Locks)
定義:
又稱寫鎖歐哲獨占鎖,如果事務T1對資料對象O1加上拍他鎖,那麼在整個枷鎖期間,隻允許事務T1對O1進行讀取和更新操作,通過Zookeeper上的一個資料節點就可以表示一個鎖。
擷取鎖:
在需要擷取排他鎖的時候,所有的用戶端都會嘗試調用create()接口,Zookeeper會保證所有的用戶端,最終隻會有一個用戶端能夠建立成功,那麼久可以認為該用戶端擷取了鎖。
釋放鎖:
在下面兩種情況都可能釋放鎖
- 擷取鎖的用戶端發生當機,Zookeeper上臨時節點就會被移除。
- 正常業務邏輯執行完成後,用戶端會主動删除建立的臨時節點。
共享鎖(Shared Locks)
定義:
又稱讀鎖,如果事務T1對O1加上了共享鎖,那麼目前事務隻能對O1進行讀取操作,其他事務也隻能對整個資料對象加上共享鎖-直到該資料對象上的所有共享鎖都被釋放。
和排他鎖一樣,是通過Zookeeper上的資料節點表示一個鎖
擷取鎖:
在需要擷取共享鎖時,所有的用戶端都會到/shared_locks整個節點下面建立一個臨時順序節點,如果是讀請求,就建立R-000000001節點,如果是寫請求,就視窗W-000000001節點 。
根據共享鎖的定義,不同的事務,可以對同一個資料對象進行讀取操作,而更新操作必須在目前沒有任務事務進行讀寫的情況下進行。對節點進行分布式讀寫順序大概分為四個步驟:
- 建立完節點之後,擷取/shared_locks下面的所有子節點,并對該節點注冊子節點變更的Watcher監聽
- 确定自己的節點需要在所有子節點中的順序。
- 對于讀請求,如果沒有比自己序号小的子節點,或者所有比自己序号小的節點都是讀請求,那麼表明自己已經成功擷取共享鎖。如果比自己序号小的節點有寫請求,那麼就進行等待。
- 接收到Watcher通知,重複步驟1
釋放鎖:
在下面兩種情況都可能釋放鎖
- 擷取鎖的用戶端發生當機,Zookeeper上臨時節點就會被移除。
- 正常業務邏輯執行完成後,用戶端會主動删除建立的臨時節點。
九、分布式隊列
隊列是先進先出,實作和共享鎖非常相似,用戶端都會到/queue_fifo節點下面建立一個臨時順序節點
建立完之後,根據如下四個步驟覺得執行順序:
- 通過調用getChildren()接口來擷取/queue_fifo節點下面的所有子節點,即擷取隊列中的所有元素。
- 确定自己的節點在所有子節點中的順序。
- 如果自己不是序号最小的節點,就需要等待,同時向比自己序号小的最後一個節點注冊Watcher監聽。
- 接收到監聽之後,重複步驟1