官網
- 官方文檔上這么解釋zookeeper,它是一個分布式服務框架,是Apache Hadoop 的一個子項目,它主要是用來解決分布式應用中經常遇到的一些數(shù)據(jù)管理問題,如:統(tǒng)一命名服務、狀態(tài)同步服務、集群管理、分布式應用配置項的管理等
- 上面的解釋有點抽象,簡單來說: zookeeper=文件系統(tǒng)+監(jiān)聽通知機制。
1、文件系統(tǒng)
Zookeeper維護一個類似文件系統(tǒng)的數(shù)據(jù)結構:
- image
每個子目錄項如 NameService 都被稱作為 znode(目錄節(jié)點),和文件系統(tǒng)一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在于znode是可以存儲數(shù)據(jù)的。
- 有四種類型的znode:
- PERSISTENT-持久化目錄節(jié)點
客戶端與zookeeper斷開連接后,該節(jié)點依舊存在
- PERSISTENT_SEQUENTIAL-持久化順序編號目錄節(jié)點
客戶端與zookeeper斷開連接后,該節(jié)點依舊存在,只是Zookeeper給該節(jié)點名稱進行順序編號
- EPHEMERAL-臨時目錄節(jié)點
客戶端與zookeeper斷開連接后,該節(jié)點被刪除
- EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節(jié)點
客戶端與zookeeper斷開連接后,該節(jié)點被刪除,只是Zookeeper給該節(jié)點名稱進行順序編號
2、 監(jiān)聽通知機制
- 客戶端注冊監(jiān)聽它關心的目錄節(jié)點,當目錄節(jié)點發(fā)生變化(數(shù)據(jù)改變、被刪除、子目錄節(jié)點增加刪除)時,zookeeper會通知客戶端。
Zookeeper功能簡介
- ZooKeeper 是一個開源的分布式協(xié)調服務,由雅虎創(chuàng)建,是 Google Chubby 的開源實現(xiàn)。 分布式應用程序可以基于 ZooKeeper 實現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負載均衡、命名服務、分布式協(xié) 調/通知、集群管理、Master 選舉、分布式鎖和分布式隊列 等功能
Zookeeper基本概念
集群角色
- Leader (領導)
Follower (追隨者)
Observer (觀察員)
- Leader (領導)
一個 ZooKeeper 集群同一時刻只會有一個 Leader,其他都是 Follower 或 Observer。ZooKeeper 配置很簡單,每個節(jié)點的配置文件(zoo.cfg)都是一樣的,只有 myid 文件不一樣。myid 的值必須是 zoo.cfg中server.{數(shù)值} 的{數(shù)值}部分。
zoo.cfg 配置示例
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logdata
tickTime=2000
initLimit=5
syncLimit=2
clientPort=2181
#集群配置
server.0=192.168.1.100:2888:3888
server.1=192.168.1.101:2888:3888
server.2=192.168.1.102:2888:3888
節(jié)點讀寫服務分工
1、ZooKeeper 集群的所有機器通過一個 Leader 選舉過程來選定一臺被稱為『Leader』 的機器,Leader服務器為客戶端提供讀和寫服務。
2、Follower 和 Observer 都能提供讀服務,不能提供寫服務。兩者唯一的區(qū)別在于, Observer機器不參與 Leader 選舉過程,也不參與寫操作的『過半寫成功』策略,因 此 Observer 可以在不影響寫性能的情況下提升集群的讀性能。
session
Session 是指客戶端會話,在講解客戶端會話之前,我們先來了解下客戶端連接。在 ZooKeeper 中,一個客戶端連接是指客戶端和 ZooKeeper 服務器之間的TCP長連接。
ZooKeeper 對外的服務端口默認是2181,客戶端啟動時,首先會與服務器建立一個TCP 連接,從第一次連接建立開始,客戶端會話的生命周期也開始了,通過這個連接,客戶端能夠通 過心跳檢測和服務器保持有效的會話,也能夠向 ZooKeeper 服務器發(fā)送請求并接受響應,同 時還能通過該連接接收來自服務器的 Watch 事件通知。
Session 的 SessionTimeout 值用來設置一個客戶端會話的超時時間。當由于服務器 壓力太大、網絡故障或是客戶端主動斷開連接等各種原因導致客戶端連接斷開時,只要在 SessionTimeout 規(guī)定的時間內能夠重新連接上集群中任意一臺服務器,那么之前創(chuàng)建的會話 仍然有效。
數(shù)據(jù)節(jié)點
zookeeper的結構其實就是一個樹形結構,leader就相當于其中的根結點,其它節(jié)點就相當于 follow節(jié)點,每個節(jié)點都保留自己的數(shù)據(jù)在內存中。
zookeeper的節(jié)點分兩類:持久節(jié)點和臨時節(jié)點
- 持久節(jié)點 :僅顯式刪除才消失;持久節(jié)點是指一旦這個 樹形結構上被創(chuàng)建了,除非主動進行對樹節(jié)點的移除操 作,否則這個 節(jié)點將一直保存在 ZooKeeper 上。
- 臨時節(jié)點 : 會話終止即自動消失;臨時節(jié)點的生命周期跟客戶端會話綁定,一旦客戶端會話失效,那么這個客戶端創(chuàng) 建的所有臨時節(jié)點都會被移除。
狀態(tài)信息
- 每個節(jié)點除了存儲數(shù)據(jù)內容之外,還存儲了 節(jié)點本身的一些狀態(tài)信息。用 get 命令可以 同時獲得某個 節(jié)點的內容和狀態(tài)信息 在 ZooKeeper 中,version 屬性是用來實現(xiàn)樂觀鎖機制中的『寫入校驗』的(保證分布 式數(shù)據(jù)原子性操作)。
事務操作
- 在ZooKeeper中,能改變ZooKeeper服務器狀態(tài)的操作稱為事務操作。一般包括數(shù)據(jù)節(jié)點 創(chuàng)建與刪除、數(shù)據(jù)內容更新和客戶端會話創(chuàng)建與失效等操作。對應每一個事務請求,ZooKeeper 都會為其分配一個全局唯一的事務ID,用 ZXID 表示,通常是一個64位的數(shù)字。每一個 ZXID 對應一次更新操作,從這些 ZXID 中可以間接地識別出 ZooKeeper 處理這些事務操作請求的 全局順序。
Watcher(事件監(jiān)聽)
- 事件監(jiān)聽是 ZooKeeper 中一個很重要的特性。ZooKeeper允許用戶在指定節(jié)點上注冊一些 Watcher, 并且在一些特定事件觸發(fā)的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去。該 機制是 ZooKeeper 實現(xiàn)分布式協(xié)調服務的重要特性。
Zookeeper應用場景
- ZooKeeper 是一個高可用的分布式數(shù)據(jù)管理與協(xié)調框架?;趯AB算法的實現(xiàn),該框架 能夠很好地保證分布式環(huán)境中數(shù)據(jù)的一致性。也是基于這樣的特性,使得 ZooKeeper 成為了 解決分布式一致性問題的利器。
ZAB協(xié)議 : (zookeeper原子廣播協(xié)議),它主要支持崩潰恢復機制,在leader節(jié)點進程崩潰時立即選出新的leader,并且提供數(shù)據(jù)完整性。
數(shù)據(jù)發(fā)布與訂閱(配置中心)
數(shù)據(jù)發(fā)布與訂閱,即所謂的配置中心,顧名思義就是發(fā)布者將數(shù)據(jù)發(fā)布到 ZooKeeper 節(jié)點上, 供訂閱者進行數(shù)據(jù)訂閱,進而達到動態(tài)獲取數(shù)據(jù)的目的,實現(xiàn)配置信息的集中式管理和動態(tài)更新。
對于:數(shù)據(jù)量通常比較小。數(shù)據(jù)內容在運行時動態(tài)變化。集群中各機器共享,配置一致。 這樣的全局配置信息就可以發(fā)布到 ZooKeeper上,讓客戶端(集群的機器)去訂閱該消息。
發(fā)布/訂閱系統(tǒng)一般有兩種設計模式,分別是推(Push)和拉(Pull)模式。
- ? 推模式:服務端主動將數(shù)據(jù)更新發(fā)送給所有訂閱的客戶端
- ? 拉模式:客戶端主動發(fā)起請求來獲取最新數(shù)據(jù),通常客戶端都采用定時輪詢拉取的方式
ZooKeeper 采用的是推拉相結合的方式: 客戶端想服務端注冊自己需要關注的節(jié)點,一旦該節(jié)點的數(shù)據(jù)發(fā)生變更,那么服務端就會向相應 的客戶端發(fā)送Watcher事件通知,客戶端接收到這個消息通知后,需要主動到服務端獲取最新的數(shù)據(jù)。
命名服務
命名服務也是分布式系統(tǒng)中比較常見的一類場景。在分布式系統(tǒng)中,通過使用命名服務,客戶端 應用能夠根據(jù)指定名字來獲取資源或服務的地址,提供者等信息。被命名的實體通??梢允羌褐械?機器,提供的服務,遠程對象等等——這些我們都可以統(tǒng)稱他們?yōu)槊帧?/p>
其中較為常見的就是一些分布式服務框架(如RPC)中的服務地址列表。通過在ZooKeepr里 創(chuàng)建順序節(jié)點,能夠很容易創(chuàng)建一個全局唯一的路徑,這個路徑就可以作為一個名字。
ZooKeeper 的命名服務即生成全局唯一的ID。
分布式協(xié)調服務/通知
- ZooKeeper 中特有 Watcher 注冊與異步通知機制,能夠很好的實現(xiàn)分布式環(huán)境下不同機器, 甚至不同系統(tǒng)之間的通知與協(xié)調,從而實現(xiàn)對數(shù)據(jù)變更的實時處理。使用方法通常是不同的客戶端 如果 機器節(jié)點 發(fā)生了變化,那么所有訂閱的客戶端都能夠接收到相應的Watcher通知,并做出相應 的處理。 ZooKeeper的分布式協(xié)調/通知,是一種通用的分布式系統(tǒng)機器間的通信方式。
master選舉
當leader崩潰或者leader失去大多數(shù)的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的Server都恢復到一個正確的狀態(tài)。Zk的選舉算法有兩種:一種是基于basic paxos實現(xiàn)的,另外一種是基于fast paxos算法實現(xiàn)的。系統(tǒng)默認的選舉算法為fast paxos。先介紹basic paxos流程:
1 .選舉線程由當前Server發(fā)起選舉的線程擔任,其主要功能是對投票結果進行統(tǒng)計,并選出推薦的Server;
2 .選舉線程首先向所有Server發(fā)起一次詢問(包括自己);
3 .選舉線程收到回復后,驗證是否是自己發(fā)起的詢問(驗證zxid是否一致),然后獲取對方的id(myid),并存儲到當前詢問對象列表中,最后獲取對方提議的leader相關信息(id,zxid),并將這些信息存儲到當次選舉的投票記錄表中;
- 收到所有Server回復以后,就計算出zxid最大的那個Server,并將這個Server相關信息設置成下一次要投票的Server;
- 線程將當前zxid最大的Server設置為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數(shù), 設置當前推薦的leader為獲勝的Server,將根據(jù)獲勝的Server相關信息設置自己的狀態(tài),否則,繼續(xù)這個過程,直到leader被選舉出來。
分布式鎖
- 分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式 ,分布式鎖又分為排他鎖和共享鎖兩種
排它鎖 :ZooKeeper如何實現(xiàn)排它鎖
定義鎖: ZooKeeper 上的一個 機器節(jié)點 可以表示一個鎖
獲得鎖: 把ZooKeeper上的一個節(jié)點看作是一個鎖,獲得鎖就通過創(chuàng)建臨時節(jié)點的方式來實現(xiàn)。ZooKeeper 會保證在所有客戶端中,最終只有一個客戶端能夠創(chuàng)建成功,那么就可以認為該客戶端獲得了鎖。同時,所有沒有獲取到鎖的客戶端就需要到/exclusive_lock
節(jié)點上注冊一個子節(jié)點變更的Watcher監(jiān)聽,以便實時監(jiān)聽到lock節(jié)點的變更情況。釋放鎖: 因為鎖是一個臨時節(jié)點,釋放鎖有兩種方式
當前獲得鎖的客戶端機器發(fā)生宕機或重啟,那么該臨時節(jié)點就會被刪除,釋放鎖
正常執(zhí)行完業(yè)務邏輯后,客戶端就會主動將自己創(chuàng)建的臨時節(jié)點刪除,釋放鎖。
無論在什么情況下移除了lock節(jié)點,ZooKeeper 都會通知所有在 /exclusive_lock 節(jié)點上注冊了節(jié)點變更 Watcher 監(jiān)聽的客戶端。這些客戶端在接收到通知后,再次重新發(fā)起分布式鎖獲取,即重復『獲取鎖』過程。
共享鎖
- 共享鎖在同一個進程中很容易實現(xiàn),但是在跨進程或者在不同 Server 之間就不好實現(xiàn)了。Zookeeper 卻很容易實現(xiàn)這個功能,實現(xiàn)方式也是需要獲得鎖的 Server 創(chuàng)建一個 EPHEMERAL_SEQUENTIAL 目錄節(jié)點,然后調用 getChildren方法獲取當前的目錄節(jié)點列表中最小的目錄節(jié)點是不是就是自己創(chuàng)建的目錄節(jié)點,如果正是自己創(chuàng)建的,那么它就獲得了這個鎖,如果不是那么它就調用 exists(String path, boolean watch) 方法并監(jiān)控 Zookeeper 上目錄節(jié)點列表的變化,一直到自己創(chuàng)建的節(jié)點是列表中最小編號的目錄節(jié)點,從而獲得鎖,釋放鎖很簡單,只要刪除前面它自己所創(chuàng)建的目錄節(jié)點就行了。
