zookeeper源碼分析系列一開篇基礎知識剖析

目錄

最近開始對zookeeper源碼進行學習,本篇為zookeeper源碼學習的開篇,從整體上對zookeeper進行剖析.

一、ZooKeeper總體介紹

1.1、什么是zookeeper

ZooKeeper 是一個分布式的,開放源碼的分布式應用程序協同服務+存儲系統,同時是一款世界級的優秀開源產品,在大數據生態系統中 Hadoop、Storm、HBase、Spark、Flink、Kafka 隨處都是 ZooKeeper的應用場景。特別是在粗粒度分布式鎖、分布式選主、主備高可用切換等不需要高 TPS 的場景下有不可替代的作用。

1.2、ZooKeeper 應用場景

很多分布式協調服務都可以用 ZooKeeper 來做,其中典型應用場景如下:
1、配置管理:比如微服務系統,各個獨立服務都要使用集中化的配置管理,這個時候就需要 ZooKeeper。
2、組成員管理:比如上面講到的 HBase 其實就是用來做集群的組成員管理。
3、各種分布式鎖:ZooKeeper 適用于存儲和協同相關的關鍵數據,不適合用于大數據量存儲。如果要存 KV 或者大量的業務數據,還是要用數據庫或者其他 NoSql 來做。
4、注冊中心:大多數中小型公司都用zk來做注冊中心

至于為什么 ZooKeeper 不適合大數據量存儲呢?主要有以下兩個原因:
1、設計方面:ZooKeeper 需要把所有的數據(它的 data tree)加載到內存中。這就決定了ZooKeeper 存儲的數據量受內存的限制。一般的數據庫系統例如 MySQL可以存儲大于內存的數據,這是因為 InnoDB 是基于 B-Tree 的存儲引擎(基于內存+磁盤一致性)。
2、工程方面:ZooKeeper 的設計目標是為協同服務提供數據存儲,數據的高可用性和性能是最重要的系統指標,處理大數量不是 ZooKeeper 的首要目標。因此,ZooKeeper 不會對大數量存儲做太多工程上的優化。

二.ZooKeeper源碼環境

2.1、ZooKeeper版本選擇

在了解任何技術源碼的時候,最重要的兩件事要搞清楚:
1、版本如何選擇
2、源碼環境準備
zookeeper的大版本:
1、zookeeper-3.4.x 企業最常用,大數據技術組件最常用
2、zookeeper-3.5.x
3、zookeeper-3.6.x
最總結論:zookeeper-3.4.14.tar.gz,安裝包就是源碼包, ZooKeeper-3.5 以上,源碼 和 安裝包就分開了。

2.2、 ZooKeeper源碼環境準備

1、準備一個IDE:IDEA
2、從官網下載源碼包,IDEA去導入這個源碼項目即可
3、稍微等待一下,maven去下載一些依賴jar
4、從官網下載 zookeeper-3.4.14.tar.gz 安裝包,該安裝包直接包含源碼或者從 github 去拉取源碼項目

三.ZooKeeper基礎之序列化機制

3.1、序列化使用場景

1、當在網絡中需要進行消息,數據傳輸,那么這些數據就需要進行序列化和反序列化
2、當數據需要被持久化到磁盤的時候

3.2、什么是序列化, 為什么要進行序列化操作

1、序列化是指將我們定義好的 go/php/java 類型轉化成數據流的形式。之所以這么做是因為在網絡傳輸過程中,TCP 協議采用“流通信”的方式,提供了可以讀寫的字節流
2、任何一個分布式系統的底層,都必然會有網絡通信,這就必然要提供一個分布式通信框架和序列化機制。所以我們在看 ZooKeeper 源碼之前,先搞定 ZooKeeper 網絡通信和序列化。

3.3、序列化實現方式

3.3.1、java序列化實現

Java 中進行序列化和反序列化的過程中,主要使用 ObjectInputStream 和 ObjectOutputStream 來進行具體的序列化和反序列化。


java序列化
3.3.2、hadoop的序列化實現
hadoop的序列化實現
3.3.3、ZooKeeper 中的序列化機制
ZooKeeper 中的序列化機制

序列化的 API 主要在 zookeeper-jute 子項目中。

3.3.4、重點API:
org.apache.jute

org.apache.jute.InputArchive:反序列化需要實現的接口,其中各種 read 開頭的方法,都是反序列化方法
org.apache.jute.OutputArchive:所有進行序列化操作的都是實現這個接口,其中各種 write 開頭的方法都是序列化方法。
org.apache.jute.Index:用于迭代數據進行反序列化的迭代器
org.apache.jute.Record:在 ZooKeeper 要進行網絡通信的對象,都需要實現這個接口。里面有序列化和反序列化兩個重要的方法

四、ZooKeeper基礎之持久化機制

對于只要底層涉及到關于數據的存儲,讀寫操作, 一般都會有一個持久化機制來保證.那么ZooKeeper的數據模型主要涉及兩類知識:數據模型持久化機制, 背后是兩套API來支撐

1、數據模型 : ZKDataBase + DataTree + DataNode
2、持久化機制: TxnLog + SnapLog

ZooKeeper 本身是一個對等架構(內部選舉,從所有 learner 中選舉一個 leader, 剩下的成為follower)

1、每個節點上都保存了整個系統的所有數據(leader存儲了數據,所有的follower節點都是leader的副本節點)
2、每個節點上的都把數據放在磁盤一份,放在內存一份, 保證磁盤跟內存一致性,來平衡讀寫性能

ZooKeeper的數據模型,抽象出了重要的三個API用來完成數據的管理:

1、ZKDataBase 負責管理 DataTree ,執行 DataTree 的相關 快照和恢復的操作
2、DataTree znode系統的完整抽象, 整個數據樹結構
3、DataNode znode 系統中的一個節點的抽象

關于 ZooKeeper 中的數據在內存中的組織,其實就是一棵樹:

1、這棵樹就叫做:DataTree (抽象了一棵樹)
2、這棵樹上的節點:DataNode (抽象一個節點)
3、關于管理這個 DataTree 的組件就是 ZKDataBase (內存數據庫:針對 DataTree 能做各種操作)

ZooKeeper 的持久化的一些操作接口,都在org.apache.zookeeper.server.persistence 包中。


org.apache.zookeeper.server.persistence

日志操作

內存快照操作

主要的類的介紹:

第一組:主要是用來操作日志的(如果客戶端往zk中寫入一條數據,則記錄一條日志)
TxnLog,接口,讀取事務性日志的接口。
FileTxnLog,實現TxnLog接口,添加了訪問該事務性日志的API。
第二組:拍攝快照(當內存數據持久化到磁盤)
Snapshot,接口類型,持久層快照接口。
FileSnap,實現Snapshot接口,負責存儲、序列化、反序列化、訪問快照。
第三組;兩個成員變量:TxnLog和SnapShot
FileTxnSnapLog,封裝了TxnLog和SnapShot。
第四組:工具類
Util,工具類,提供持久化所需的API。

五、ZooKeeper基礎之網絡通信機制

Java IO 有幾個種類:

1、BIO JDK-1.1(編碼簡單,效率低) 阻塞模型
2、NIO JDK-1.4(效率有提升,編碼復雜) 基于reactor實現的異步非阻塞網絡通信模型 通常的IO的選擇:
1)、原生NIO 2)、基于NIO實現的網絡通信框架:netty
3、AIO JDK-1.7(效率最高,編碼復雜度一般) 真正的異步非阻塞通信模型

NIO 的三大API:

1、Buffer
2、Channel
3、Selector

ZooKeeper 中的通信有兩種方式:

1、NIO,默認使用NIO
2、Netty

兩個最重要的API:

ServerCnxn 服務端的通信組件
ClientCnxn 客戶端的通信組件

關于客戶端和服務端的一個定義:誰發請求,誰就是客戶端,誰接收和處理請求,誰就是服務端

1、真正的client給zookeeper發請求
2、zookeeper中的leader給follower發命令
3、zookeeper中的followe給leader發請求

ServerCnxn實現包:org.apache.zookeeper.server.ServerCnxn


ServerCnxn實現包

詳細說明:
Stats,表示ServerCnxn上的統計數據。
Watcher,表示事件處理,監聽器
ServerCnxn,表示服務器連接,表示一個從客戶端到服務器的連接。
ClientCnxn,存在于客戶端用來執行通信的組件
NettyServerCnxn,基于Netty的連接的具體實現。
NIOServerCnxn,基于NIO的連接的具體實現。

六、Zookeeper基礎之Watcher工作機制

客戶端的 Watcher 注冊:

1、org.apache.zookeeper.ZooKeeper:客戶端基礎類、存儲了ClientCnxn和ZkWatcherManager
2、ZKWatchManager:ZooKeeper的內部類,實現了ClientWatchManager接口,主要用來存儲各種類型的Watcher,主要有三種:dataWatches、existWatches、childWatches以及一個默認的defaultWatcher
3、org.apache.zookeeper.ClientCnxn:與服務端的交互類,主要包含以下對象:LinkedListoutgoingQueue、SendThread 和 EventThread,其中outgoingQueue未待發送給服務端的Packet列表,SendThread線程負責和服務端進行請求交互,而EventThread線程則負責客戶端Watcher事件的回調執行
4、WatchRegistration:Zookeeper的內容類,包裝了Watcher和clientPath,并且負責Watcher的注冊
5、Packet:ClientCnxn的內部類,與Zookeeper服務端通信的交互類

watcher實現

兩條主線

1、實現主線:Watcher + WatchedEvent
2、管理主線:WatchManager(負責響watcher.process(watchedEvent)) + ZKWatchManager(負責注冊等相關管理)

watcher實現

組件說明:

Watcher,接口類型,其定義了process方法,需子類實現。
Event,接口類型,Watcher的內部類,無任何方法。
KeeperState,枚舉類型,Event的內部類,表示Zookeeper所處的狀態。
EventType,枚舉類型,Event的內部類,表示Zookeeper中發生的事件類型。
WatchedEvent,表示對ZooKeeper上發生變化后的反饋,包含了KeeperState和EventType。
ClientWatchManager,接口類型,表示客戶端的Watcher管理者,其定義了materialized方法,需子類實現。
ZKWatchManager,Zookeeper的內部類,繼承ClientWatchManager。
MyWatcher,ZooKeeperMain的內部類,繼承Watcher。
ServerCnxn,接口類型,繼承Watcher,表示客戶端與服務端的一個連接。
WatchManager,管理Watcher。

Watcher 主要工作流程:

1、用戶調用 Zookeeper 的 getData 方法,并將自定義的 Watcher 以參數形式傳入,該方法的作用主要是封裝請求,然后調用 ClientCnxn 的 submitRequest 方法提交請求
2、 ClientCnxn 在調用 submitRequest 提交請求時,會將 WatchRegistration(封裝了我們傳入的Watcher 和clientPath )以參數的形式傳入,submitRequest 方法主要作用是將信息封裝成Packet(ClientCnxn的內部類),并將封裝好的 Packet 加入到 ClientCnxn 的待發送列表中(LinkedList outgoingQueue)
3、 SendThread 線程不斷地從 outgoingQueue 取出未發送的 Packet 發送給客戶端并且將該 Packet加入pendingQueue (等待服務器響應的Packet列表)中,并通過自身的 readResponse 方法接收服務端的響應
4、SendThread 接收到客戶端的響應以后,會調用 ClientCnxn 的finishPacket 方法進行 Watcher方法的注冊
5、在 finishPacket 方法中,會取出 Packet 中的 WatchRegistration 對象,并調用其 register 方法,從ZKWatchManager 取出對應的 dataWatches、existWatches 或者 childWatches 其中的一個Watcher 集合,然后將自己的 Watcher 添加到該 Watcher 集合中。

未完待續,下篇接著繼續分析

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
禁止轉載,如需轉載請通過簡信或評論聯系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評論 6 529
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,916評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,014評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,245評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,795評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,010評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,524評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,487評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,634評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,884評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,236評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,623評論 2 370

推薦閱讀更多精彩內容