顧名思義 zookeeper 就是動物園管理員,他是用來管 hadoop(大象)、Hive(蜜蜂)、pig(小 豬)的管理員, Apache Hbase 和 Apache Solr 的分佈式集羣都用到了 zookeeper;Zookeeper: 是一個分佈式的、開源的程序協調服務,是 hadoop 項目下的一個子項目。他提供的主要功 能包括:配置管理、名稱服務、分佈式鎖、集羣管理。node
功能特性
- 最終一致性:client 不論鏈接到哪一個 Server,展現給它都是同一個視圖,這是 zookeeper 最重要的性能。
- 可靠性:具備簡單、健壯、良好的性能,若是消息 m 被到一臺服務器接受,那麼它 將被全部的服務器接受。
- 實時性:Zookeeper 保證客戶端將在一個時間間隔範圍內得到服務器的更新信息,或 者服務器失效的信息。但因爲網絡延時等緣由,Zookeeper 不能保證兩個客戶端能同時獲得 剛更新的數據,若是須要最新數據,應該在讀數據以前調用 sync()接口。
- 等待無關(wait-free):慢的或者失效的 client 不得干預快速的 client 的請求,使得每 個 client 都能有效的等待。
- 原子性:更新只能成功或者失敗,沒有中間狀態。
順序性:包括全局有序和偏序兩種:全局有序是指若是在一臺服務器上消息 a 在消息 b 前發佈,則在全部 Server 上消息 a 都將在消息 b 前被髮布;偏序是指若是一個消息 b 在消 息 a 後被同一個發送者發佈,a 必將排在 b 前面。算法
進程角色
- 集羣的兩種模式
- 恢復模式:集羣的一種非穩定狀態,集羣不能處理外部請求;集羣啓動或遇到leader崩潰時,集羣進入恢復模式,在本模式中選舉leader,leader選舉完成後其餘節點與leader進行數據同步,當過半節點完成同步後恢復模式結束,進入廣播模式。
- 廣播模式:集羣的穩定狀態,集羣能正常的處理外部請求;此時如有新節點加入,新節點會自動從leader同步數據。
- 集羣啓動過程:
- leader選舉原則
- 集羣中只有超過半數的節點處於正常狀態,集羣才能穩定,才能處理外部請求。
- 集羣正常工做以前myid小的節點會優先給myid大的節點投票,直到選出leader爲止。
- 選出leader以前,集羣全部節點都處於looking狀態,選舉成功後,除leader節點外,其他節點的狀態由looking變爲following,角色也成爲了follower。
- leader選舉過程
- 假設集羣有5個節點,myid分別爲1~5,假設集羣第一次啓動,全部節點都沒有歷史數據,啓動順序1~5。由集羣節點數量可知,至少要有3個節點正常,集羣才能穩定工做。
- 節點1啓動,其初始狀態爲looking,發起一輪選舉,節點1投本身一票,因爲不過半,本輪選舉沒法完成。節點1仍然保持looking狀態。
- 節點2啓動,其初始狀態爲looking,它也發起一輪選舉,節點2投本身一票;節點1也參與進本輪投票,打算給本身投一票,可是發現節點2的myid比本身的大,就改投節點2一票;本輪投票事後節點1得0票,節點2得2票,因爲節點2的得票數不過半,因此本輪選舉未能完成;節點一、2都保持looking狀態。
- 節點3啓動,其初始狀態爲looking,它也發起一輪選舉,且節點3先投本身一票;節點一、2也都參與進本輪投票中來,打算投本身一票,發現本輪中節點3的myid大於本身的,因此節點一、2都轉投節點3一票;此時節點3就收穫了3票,超過了集羣節點的半數,節點3率先當選,並從looking狀態變爲leading狀態。節點一、2的狀態變爲following。
- 節點4啓動,其初始狀態爲looking,它也發起一輪選舉;此時因爲節點一、2處於following狀態,這兩個節點就不參與本輪選舉。節點4本打算投本身一票,可是發現節點3已進入leading狀態,且票數已通過半,此時節點4就會將本身的一票轉投給節點3。節點4未收到投票,狀態由looking變爲following。
- 節點5的啓動過程與節點4同樣,最終未得到投票,也處於following狀態。
- 最終節點3成爲leader,節點一、二、四、5成爲follower。
- 崩潰恢復過程:當leader崩潰後,集羣中的其餘follower節點會從新變爲looking狀態,從新進行leader選舉。選舉過程同啓動時的leader選舉同樣。
- 消息廣播算法:
- Znode
在 Zookeeper 中,znode 是一個跟 Unix 文件系統路徑類似的節點,能夠往這個節點存儲 或獲取數據。 Zookeeper 底層是一套數據結構。這個存儲結構是一個樹形結構,其上的每個節點, 咱們稱之爲「znode」 zookeeper 中的數據是按照「樹」結構進行存儲的。並且 znode 節點還分爲 4 中不一樣的類 型。 每個 znode 默認可以存儲 1MB 的數據(對於記錄狀態性質的數據來講,夠了) 可使用 zkCli 命令,登陸到 zookeeper 上,並經過 ls、create、delete、get、set 等命令 操做這些 znode 節點
- Znode 節點類型
- bin:放置運行腳本和工具腳本,若是是 Linux 環境還會有有 zookeeper 的運 行日誌 zookeeper.out
- conf:zookeeper 默認讀取配置的目錄,裏面會有默認的配置文件
- contrib:zookeeper 的拓展功能
- dist-maven:zookeeper的 maven 打包目錄
- docs:zookeeper 相關的文檔
- lib:zookeeper 核心的 jar
- recipes:zookeeper 分佈式相關的 jar 包
src:zookeeper 源碼緩存
單機部署
Zookeeper 在啓動時默認的去 conf 目錄下查找一個名稱爲 zoo.cfg 的配置文件。 在 zookeeper 應用目錄中有子目錄 conf。其中有配置文件模板,手動拷貝重命名:zoo_sample.cfg cp zoo_sample.cfg zoo.cfg。zookeeper 應用中的配置文件爲 conf/zoo.cfg。 修改配置文件 zoo.cfg - 設置數據緩存路徑
安裝jdk,配置相關環境變量,上傳zookeeper壓縮包
[zk_hom]# tar -zxvf apache-zookeeper-3.5.5-bin.tar.gz //解壓
[zk_hom]# mkdir zkdata //新建一個數據持久化目錄
[zk_hom]# cd conf //進入配置目錄
[zk_hom/confg]# cp zoo_example.cfg zoo.cfg //複製配置文件樣本,並重命名未zoo.cfg
編解zoo.cfg,將其中的dataDir = zk_home/zkdata
[zk_hom/bin]# sh ./zkServer.sh start //啓動節點
[zk_hom/bin]# sh ./zkServer.sh status //查看節點狀態服務器
集羣部署
- 各個節點上的準備工做同單機的同樣,都須要jdk,zookeeper壓縮包,同時要拷貝配置並配置數據持久化目錄,同時爲各節點新建持久化目錄。
- 不一樣的是須要在各節點的zookeeper持久化目錄中新建一個名爲「myid」的文件,文件中各自寫上節點編號1~5。
- 配置文件中須要追加集羣中其餘節點的訪問地址:
【server.myid = ip:通訊端口:選舉端口】
server.1 = 192.168.50.1:2181:3181
server.2 = 192.168.50.2:2181:3181
server.3 = 192.168.50.3:2181:3181
server.4 = 192.168.50.4:2181:3181
server.5 = 192.168.50.5:2181:3181
啓動各個節點網絡
應用管理
bin/zkServer.sh start //開啓服務
bin/zkServer.sh status //查看服務狀態
bin/zkServer.sh stop //中止服務端
bin/zkCli.sh -server 192.168.199.175:2181 //使用客戶端鏈接服務端數據結構
客戶端命令
應用場景
- 配置管理
在咱們的應用中除了代碼外,還有一些就是各類配置。好比數據庫鏈接等。通常咱們都 是使用配置文件的方式,在代碼中引入這些配置文件。當咱們只有一種配置,只有一臺服務 器,而且不常常修改的時候,使用配置文件是一個很好的作法,可是若是咱們配置很是多, 有不少服務器都須要這個配置,這時使用配置文件就不是個好主意了。這個時候每每須要尋 找一種集中管理配置的方法,咱們在這個集中的地方修改了配置,全部對這個配置感興趣的 均可以得到變動。Zookeeper 就是這種服務,它使用 Zab 這種一致性協議來提供一致性。現 在有不少開源項目使用 Zookeeper 來維護配置,好比在 HBase 中,客戶端就是鏈接一個 Zookeeper,得到必要的 HBase 集羣的配置信息,而後才能夠進一步操做。還有在開源的消 息隊列 Kafka 中,也使用 Zookeeper來維護broker的信息。在 Alibaba開源的 SOA 框架Dubbo 中也普遍的使用 Zookeeper 管理一些配置來實現服務治理。
- 名稱服務
名稱服務這個就很好理解了。好比爲了經過網絡訪問一個系統,咱們得知道對方的 IP 地址,可是 IP 地址對人很是不友好,這個時候咱們就須要使用域名來訪問。可是計算機是 不能是域名的。怎麼辦呢?若是咱們每臺機器裏都備有一份域名到 IP 地址的映射,這個倒 是能解決一部分問題,可是若是域名對應的 IP 發生變化了又該怎麼辦呢?因而咱們有了 DNS 這個東西。咱們只須要訪問一個你們熟知的(known)的點,它就會告訴你這個域名對應 的 IP 是什麼。在咱們的應用中也會存在不少這類問題,特別是在咱們的服務特別多的時候, 若是咱們在本地保存服務的地址的時候將很是不方便,可是若是咱們只須要訪問一個你們都 熟知的訪問點,這裏提供統一的入口,那麼維護起來將方便得多了。
- 分佈式鎖
其實在第一篇文章中已經介紹了 Zookeeper 是一個分佈式協調服務。這樣咱們就能夠利 用 Zookeeper 來協調多個分佈式進程之間的活動。好比在一個分佈式環境中,爲了提升可靠 性,咱們的集羣的每臺服務器上都部署着一樣的服務。可是,一件事情若是集羣中的每一個服 務器都進行的話,那相互之間就要協調,編程起來將很是複雜。而若是咱們只讓一個服務進 行操做,那又存在單點。一般還有一種作法就是使用分佈式鎖,在某個時刻只讓一個服務去幹活,當這臺服務出問題的時候鎖釋放,當即 fail over 到另外的服務。這在不少分佈式系統 中都是這麼作,這種設計有一個更好聽的名字叫 Leader Election(leader 選舉)。好比 HBase 的 Master 就是採用這種機制。但要注意的是分佈式鎖跟同一個進程的鎖仍是有區別的,所 以使用的時候要比同一個進程裏的鎖更謹慎的使用。
- 集羣管理
在分佈式的集羣中,常常會因爲各類緣由,好比硬件故障,軟件故障,網絡問題,有些 節點會進進出出。有新的節點加入進來,也有老的節點退出集羣。這個時候,集羣中其餘機 器須要感知到這種變化,而後根據這種變化作出對應的決策。好比咱們是一個分佈式存儲系 統,有一箇中央控制節點負責存儲的分配,當有新的存儲進來的時候咱們要根據如今集羣目 前的狀態來分配存儲節點。這個時候咱們就須要動態感知到集羣目前的狀態。還有,好比一 個分佈式的 SOA 架構中,服務是一個集羣提供的,當消費者訪問某個服務時,就須要採用 某種機制發現如今有哪些節點能夠提供該服務(這也稱之爲服務發現,好比 Alibaba 開源的 SOA 框架 Dubbo 就採用了 Zookeeper 做爲服務發現的底層機制)。還有開源的 Kafka 隊列就 採用了 Zookeeper 做爲 Cosnumer 的上下線管理。
- 負載均衡的集羣管理