一文入門Zookeeper
一、什麼是Zookeeper
1.1 概述
在我的印象中,zookeeper是可以作為註冊中心來存在的,之前的微服務架構更多的是採用Dubbo+zookeeper來搭配著使用的,因此,zookeeper它是主要服務於分散式系統。
而分散式系統的特點就是會有多個節點存在,實時感知每個節點的狀態,管理每個節點就變得尤為重要。而zookeeper的出現就解決了這個問題。 從設計模式角度來理解:它是一個基於觀察者模式設計的分散式服務管理框架,它負責儲存和管理大家都關心的資料,然後接受觀察者的註冊,一旦這些資料的狀態發生了變化,zookeeper就負責通知已經在zookeeper上註冊的那些觀察者,讓他們做出相應的反應。
因此,zookeeper可以概況為:檔案系統+通知機制。
福利 福利 福利 免費領取Java架構技能地圖 注意了是免費送
免費領取 要的+V 領取
工作機制:
- 1、服務端啟動時去註冊資訊(建立的都是臨時節點)
- 2、獲取到當前線上伺服器列表,並且註冊監聽
- 3、伺服器節點下線
- 4、伺服器節點下線事件通知
- 5、process重新再去獲取伺服器列表,並註冊監聽
1.2 特點
1、Zookeeper是設計模式是由一個領導者和多個跟隨者組成的叢集
2、半數原則:叢集中只要有半數以上的節點存活,zookeeper叢集就能正常服務
3、全域性資料一致,每個server伺服器儲存一份相同的資料副本,client無論連線到哪個server,資料都一致
4、資料更新原子性:一次資料更新要麼成功,要麼失敗。
5、實時性:在一定時間範圍內,client能夠讀到最新資料。
1.3 資料結構
zookeeper的資料模型與linux檔案系統很類似,整體可以看作是一棵樹,每個節點稱為znode,預設能夠儲存1Mb的資料,每個znode都可以通過其路徑唯一標識:
而這些節點可以分為兩類:臨時和持久。因此一個面試題產生了:zookeeper的節點型別有哪些?
- 臨時普通節點
- 臨時有序節點
- 持久普通節點
- 持久有序節點
1.4 zookeeper能幹啥?
zookeeper 提供的服務包括:統一命名服務,統一配置管理,統一叢集管理,軟負載均衡,分散式鎖。
1.4.1 統一命名服務
可以理解為訪問域名:www.baidu.com 的時候,這個域名下面有很多臺伺服器:192.168.1.100,192.168.1.101,192.168.1.102等。別人只要訪問這個域名,zookeeper就會把請求轉發給註冊過的某個伺服器上。而使用者並不用去記住訪問哪個ip地址,只需要知道這個域名就可以了。
1.4.2 統一配置管理
把公共的配置檔案抽取出來,分發給其他系統。
配置檔案同步非常常見。一般要求一個叢集中,所有的節點的配置資訊是一致的,比如kafka叢集,對配置檔案修改後,希望能夠快速同步到各個配置上。
1.4.3 統一叢集管理
1)分散式環境中,實時掌握每個節點的狀態是必要的,可根據節點實時狀態進行調整。
2) zookeeper 可以實現實時監控節點狀態變化。
- 可將節點資訊寫入zookeeper上的一個Znode
- 監聽這個znode可獲取它的實時狀態變化。
1.4.4 軟負載均衡
再zookeeper中記錄每臺伺服器的訪問數,讓訪問最少的伺服器去處理最新的客戶端請求。
1.4.5 分散式鎖
如果有a、b、c多個客戶端去搶一個zookeeper分散式鎖。原理是這樣的:
- 剛訪問 /lock 鎖節點的時候,大家都上來直接建立一個接一個的有序節點。例如a系統建立了001節點。b系統建立了002節點,c系統建立了003節點。
- 系統拿到所有的節點後,會比較自己的節點是不是最小的,如果是,則得到鎖,如果不是,就對上個節點加監聽器,監視它。
- 只要上一個節點釋放鎖,自己就排到前面去了,相當於一個排隊機制。
用臨時節點 第一個用意:如果某個客戶端建立臨時順序節點之後,不小心自己宕機了也沒關係,zookeeper感知到那個客戶端宕機,會自動刪除對應的臨時順序節點,相當於自動釋放鎖,或者是自動取消自己的排隊。
二、zookeeper安裝
2.1 本地模式安裝部署
1、步驟:
- 配置修改:conf下的zoo_sample.cfg修改為zoo.cfg
- 在zookeeper目錄下建立dataDir資料夾,存放資料的儲存目錄。
- 在zookeeper下面新增資料存放路徑:
dataDir=/opt/module/zookeeper-3.5.7/zkData
複製程式碼
- 啟動
[root@hadoop101 zookeeper-3.5.7]# bin/zkServer.sh start
複製程式碼
- 檢視狀態
[root@hadoop101 zookeeper-3.5.7]# bin/zkServer.sh status
複製程式碼
- 啟動客戶端 連線指定的host的zk服務
[root@hadoop101 zookeeper-3.5.7]# bin/zkCli.sh -server host:port
複製程式碼
- 停止
[root@hadoop101 zookeeper-3.5.7]# bin/zkServer.sh stop
複製程式碼
2.2 配置引數解讀
1)tickTime =2000:通訊心跳數,Zookeeper伺服器與客戶端心跳時間,單位毫秒 Zookeeper使用的基本時間,伺服器之間或客戶端與伺服器之間維持心跳的時間間隔,也就是每個tickTime時間就會發送一個心跳,時間單位為毫秒。 它用於心跳機制,並且設定最小的session超時時間為兩倍心跳時間。 (session的最小超時時間是2*tickTime)
2)initLimit =10:LF初始通訊時限 叢集中的Follower跟隨者伺服器與Leader領導者伺服器之間初始連線時能容忍的最多心跳數(tickTime的數量),用它來限定叢集中的Zookeeper伺服器連線到Leader的時限。
3)syncLimit =5:LF同步通訊時限 叢集中Leader與Follower之間的最大響應時間單位,假如響應超過syncLimit * tickTime,Leader認為Follwer死掉,從伺服器列表中刪除Follwer。
4)dataDir:資料檔案目錄+資料持久化路徑 主要用於儲存Zookeeper中的資料。
5)clientPort =2181:客戶端連線埠 監聽客戶端連線的埠
三、Zookeeper內部原理
3.1 節點型別(Znode)
持久:客戶端和伺服器斷開後,建立的節點不刪除。
1)普通持久節點
2)帶序號的持久節點(序號zookeeper自己維護)
短暫:客戶端和伺服器斷開連線後,建立的節點自己刪除。
1)普通短暫節點
2)帶序號的短暫節點(序號zookeeper自己維護)
3.2 Stat結構體
描述每個ZNode的狀態資訊
[zk: localhost:2181(CONNECTED) 12] stat /zookeeper
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
複製程式碼
(1)czxid-建立節點的事務zxid 每次修改ZooKeeper狀態都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。 事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小於zxid2,那麼zxid1在zxid2之前發生。
(2)ctime - znode被建立的毫秒數(從1970年開始)
(3)mzxid - znode最後更新的事務zxid
(4)mtime - znode最後修改的毫秒數(從1970年開始)
(5)pZxid-znode最後更新的子節點zxid
(6)cversion - znode子節點變化號,znode子節點修改次數
(7)dataversion - znode資料變化號
(8)aclVersion - znode訪問控制列表的變化號
(9)ephemeralOwner- 如果是臨時節點,這個是znode擁有者的session id。如果不是臨時節點則是0。
(10)dataLength- znode的資料長度
(11)numChildren - znode子節點數量
3.3 監聽器原理
1、原理
- 首先要有一個main()執行緒
- 在main執行緒中建立zookeeper客戶端,這時就會建立兩個執行緒,一個負責網路連線通訊(connect),一個負責監聽(listener)
- 通過connect執行緒將註冊的監聽事件傳送給zookeeper
- 在zookeeper的註冊監聽列表中將註冊的監聽事件新增到列表中
- zookeeper監聽到有資料或路徑變化,就會把這個訊息傳送
- listener執行緒內部呼叫了process()方法
2、常見的監聽
- 監聽節點資料的變化:get path
- 監聽子節點增減的變化:ls path
3.4 選舉機制
3.4.1 ZAB協議:
基於訊息傳遞且保證資料一致性的一種演算法(協議)
協議目標:
1、沒有leader的情況下選舉leader
2、有leader的情況,去儘可能保證資料一致。
3.4.2 zj叢集
(1)半數機制:叢集中半數以上機器存活,叢集可用。所以Zookeeper適合安裝奇數臺伺服器。
(2)Zookeeper 雖然在配置檔案中並沒有指定Master和Slave。但是,Zookeeper工作時,是有一個節點為Leader,其他則為Follower,Leader是通過內部的選舉機制臨時產生的。
3.4.3 機制概念
1、Serverid: 伺服器id 比如有三臺伺服器,編號分別是1,2,3
2、Zxid:資料ID
伺服器中存放的最大資料ID :值越大說明資料越新,在選舉演算法中資料越新權重越大。
3、Epoch:邏輯時鐘
或者叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個資料就會增加,然後與接收到返回的投票資訊的數值相比,根據不同的值做出不同的判斷。
4、Server狀態:選舉狀態
- LOOKing:競選
- FOLLOWING:隨從狀態
- OBSERVING:觀察狀態,
- LESDING:領導者狀態。
3.4.4選舉過程
假設有五臺伺服器組成的Zookeeper 叢集,它們的id從1-5 ,同時它們都是最新啟動的,也就是沒有歷史資料,在存放資料量這點上,都是一樣的。
投票原則:
- 自私原則(伺服器剛註冊的時候都會投自己一票)
- 牆頭草隨風倒原則:(發現有其他伺服器比自己厲害,就投其他伺服器)比較的東西可以為zxid 時間戳,哪個伺服器有最新的資料就投它。
過程:
(1)伺服器1啟動,發起一次選舉。伺服器1投自己一票。此時伺服器1票數一票,不夠半數以上(3票),選舉無法完成,伺服器1狀態保持為LOOKING;
(2)伺服器2啟動,再發起一次選舉。伺服器1和2分別投自己一票並交換選票資訊:此時伺服器1發現伺服器2的ID比自己目前投票推舉的(伺服器1)大,更改選票為推舉伺服器2。此時伺服器1票數0票,伺服器2票數2票,沒有半數以上結果,選舉無法完成,伺服器1,2狀態保持LOOKING
(3)伺服器3啟動,發起一次選舉。此時伺服器1和2都會更改選票為伺服器3。此次投票結果:伺服器1為0票,伺服器2為0票,伺服器3為3票。此時伺服器3的票數已經超過半數,伺服器3當選Leader。伺服器1,2更改狀態為FOLLOWING,伺服器3更改狀態為LEADING;
(4)伺服器4啟動,發起一次選舉。此時伺服器1,2,3已經不是LOOKING狀態,不會更改選票資訊。交換選票資訊結果:伺服器3為3票,伺服器4為1票。此時伺服器4服從多數,更改選票資訊為伺服器3,並更改狀態為FOLLOWING;
(5)伺服器5啟動,同4一樣當小弟。
3.4.5 leader故障後選舉
當叢集工作中,leader故障後,只要剩下的機器數大於半數,叢集能夠正常工作,但是需要重新選舉leader。選舉的過程還是進行投票,因為叢集是在工作中,因此每臺機器的id有可能不同。那麼每次投出的票(myid,zxid),先比較zxid,再比較myid,因此叢集中剩餘的機器中zxid最大的當選leader,如果zxid都一樣,理論情況下myid最大的勝出。
zxid 時間戳,最新的資料。某種意義上,可以表示當前機器中儲存的資料完整度。
3.5 寫資料流程
1)客戶端連線zk叢集的任意一臺機器,傳送寫請求
2)如果客戶端連線的zk叢集部署leader,則當前這臺機器會將客戶端的寫請求轉發給leadet
3)當leader接收到寫請求後,會將當次的寫操作構造成一個事務,對應一個zxid
4)每個follower接收到寫操作後,先將寫操作存入佇列中,並向leader反饋
5)當leader接收到叢集中半數以上的follower的反饋,則代表本次寫操作可以正常進行,
leader會再次廣播給各個follower,讓follower將寫操作進行commit(真正寫資料)
四、最後
有關zookeeper的內容還遠不止這些,這篇更多的是介紹一些zookeeper的概念,少許客戶端的命令操作就每放上來了,今天我們知道zookeeper的儲存節點和監聽機制,就可以實現很多功能。目前階段瞭解這些就夠了,有機會再深入的話,會寫後續的文章來介紹。