ZooKeeper 入門(mén)看這篇就夠了

什么是 ZooKeeper?

ZooKeeper 是一個(gè)分布式的巧号,開(kāi)放源碼的分布式應(yīng)用程序協(xié)同服務(wù)。ZooKeeper 的設(shè)計(jì)目標(biāo)是將那些復(fù)雜且容易出錯(cuò)的分布式一致性服務(wù)封裝起來(lái),構(gòu)成一個(gè)高效可靠的原語(yǔ)集颜曾,并以一系列簡(jiǎn)單易用的接口提供給用戶使用。

ZooKeeper 發(fā)展歷史

ZooKeeper 最早起源于雅虎研究院的一個(gè)研究小組秉剑。在當(dāng)時(shí)泛豪,研究人員發(fā)現(xiàn),在雅虎內(nèi)部很多大型系統(tǒng)基本都需要依賴一個(gè)類似的系統(tǒng)來(lái)進(jìn)行分布式協(xié)同侦鹏,但是這些系統(tǒng)往往都存在分布式單點(diǎn)問(wèn)題诡曙。

所以,雅虎的開(kāi)發(fā)人員就開(kāi)發(fā)了一個(gè)通用的無(wú)單點(diǎn)問(wèn)題的分布式協(xié)調(diào)框架略水,這就是 ZooKeeper价卤。ZooKeeper 之后在開(kāi)源界被大量使用,下面列出了 3 個(gè)著名開(kāi)源項(xiàng)目是如何使用 ZooKeeper:

  • Hadoop:使用 ZooKeeper 做 Namenode 的高可用渊涝。
  • HBase:保證集群中只有一個(gè) master慎璧,保存 hbase:meta 表的位置床嫌,保存集群中的 RegionServer 列表。
  • Kafka:集群成員管理炸卑,controller 節(jié)點(diǎn)選舉既鞠。

ZooKeeper 應(yīng)用場(chǎng)景

很多分布式協(xié)調(diào)服務(wù)都可以用 ZooKeeper 來(lái)做,其中典型應(yīng)用場(chǎng)景如下:

  • 配置管理(configuration management):如果我們做普通的 Java 應(yīng)用盖文,一般配置項(xiàng)就是一個(gè)本地的配置文件嘱蛋,如果是微服務(wù)系統(tǒng),各個(gè)獨(dú)立服務(wù)都要使用集中化的配置管理五续,這個(gè)時(shí)候就需要 ZooKeeper洒敏。
  • DNS 服務(wù)
  • 組成員管理(group membership):比如上面講到的 HBase 其實(shí)就是用來(lái)做集群的組成員管理。
  • 各種分布式鎖

ZooKeeper 適用于存儲(chǔ)和協(xié)同相關(guān)的關(guān)鍵數(shù)據(jù)疙驾,不適合用于大數(shù)據(jù)量存儲(chǔ)凶伙。如果要存 KV 或者大量的業(yè)務(wù)數(shù)據(jù),還是要用數(shù)據(jù)庫(kù)或者其他 NoSql 來(lái)做它碎。

為什么 ZooKeeper 不適合大數(shù)據(jù)量存儲(chǔ)呢函荣?主要有以下兩個(gè)原因:

  1. 設(shè)計(jì)方面:ZooKeeper 需要把所有的數(shù)據(jù)(它的 data tree)加載到內(nèi)存中。這就決定了ZooKeeper 存儲(chǔ)的數(shù)據(jù)量受內(nèi)存的限制扳肛。這一點(diǎn) ZooKeeper 和 Redis 比較像傻挂。一般的數(shù)據(jù)庫(kù)系統(tǒng)例如 MySQL(使用 InnoDB 存儲(chǔ)引擎的話)可以存儲(chǔ)大于內(nèi)存的數(shù)據(jù),這是因?yàn)?InnoDB 是基于 B-Tree 的存儲(chǔ)引擎挖息。B-tree 存儲(chǔ)引擎和 LSM 存儲(chǔ)引擎都可以存儲(chǔ)大于內(nèi)存的數(shù)據(jù)量金拒。
  2. 工程方面:ZooKeeper 的設(shè)計(jì)目標(biāo)是為協(xié)同服務(wù)提供數(shù)據(jù)存儲(chǔ),數(shù)據(jù)的高可用性和性能是最重要的系統(tǒng)指標(biāo)套腹,處理大數(shù)量不是 ZooKeeper 的首要目標(biāo)绪抛。因此,ZooKeeper 不會(huì)對(duì)大數(shù)量存儲(chǔ)做太多工程上的優(yōu)化电禀。

ZooKeeper 服務(wù)的使用

要使用 ZooKeeper 服務(wù)幢码,首先我們的應(yīng)用要引入 ZooKeeper 的客戶端庫(kù),然后我們客戶端庫(kù)和 ZooKeeper 集群來(lái)進(jìn)行網(wǎng)絡(luò)通信來(lái)使用 ZooKeeper 的服務(wù)尖飞,本質(zhì)上是 Client-Server 的架構(gòu)症副,我們的應(yīng)用作為一個(gè)客戶端來(lái)調(diào)用 ZooKeeper Server 端的服務(wù)。

ZooKeeper服務(wù)

ZooKeeper 數(shù)據(jù)模型

ZooKeeper層次數(shù)據(jù)模型

ZooKeeper 的數(shù)據(jù)模型是層次模型葫松。層次模型常見(jiàn)于文件系統(tǒng)瓦糕。層次模型和 key-value 模型是兩種主流的數(shù)據(jù)模型底洗。ZooKeeper 使用文件系統(tǒng)模型主要基于以下兩點(diǎn)考慮:

  1. 文件系統(tǒng)的樹(shù)形結(jié)構(gòu)便于表達(dá)數(shù)據(jù)之間的層次關(guān)系腋么。
  2. 文件系統(tǒng)的樹(shù)形結(jié)構(gòu)便于為不同的應(yīng)用分配獨(dú)立的命名空間(namespace)。

ZooKeeper 的層次模型稱作 data tree亥揖。Data tree 的每個(gè)節(jié)點(diǎn)叫做 znode珊擂。不同于文件系統(tǒng)圣勒,每個(gè)節(jié)點(diǎn)都可以保存數(shù)據(jù)。每個(gè)節(jié)點(diǎn)都有一個(gè)版本(version)摧扇,版本從 0 開(kāi)始計(jì)數(shù)圣贸。

ZooKeeper層次數(shù)據(jù)模型實(shí)例

如上圖所示的 data tree 中有兩個(gè)子樹(shù),一個(gè)用于應(yīng)用 1(/app1)和另一個(gè)用于應(yīng)用 2(/app2)扛稽。

應(yīng)用 1 的子樹(shù)實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的組成員協(xié)議:每個(gè)客戶端進(jìn)程 pi 創(chuàng)建一個(gè) znode p_i 在 /app1 下吁峻,只要 /app1/p_i 存在就代表進(jìn)程 pi 在正常運(yùn)行。

data tree 接口

ZooKeeper 對(duì)外提供一個(gè)用來(lái)訪問(wèn) data tree的簡(jiǎn)化文件系統(tǒng) API:

  • 使用 UNIX 風(fēng)格的路徑名來(lái)定位 znode,例如 /A/X 表示 znode A 的子節(jié)點(diǎn) X在张。
  • znode 的數(shù)據(jù)只支持全量寫(xiě)入和讀取用含,沒(méi)有像通用文件系統(tǒng)那樣支持部分寫(xiě)入和讀取。
  • data tree 的所有 API 都是 wait-free 的帮匾,正在執(zhí)行中的 API 調(diào)用不會(huì)影響其他 API 的完成啄骇。
  • data tree 的 API都是對(duì)文件系統(tǒng)的 wait-free 操作,不直接提供鎖這樣的分布式協(xié)同機(jī)制瘟斜。但是 data tree 的 API 非常強(qiáng)大缸夹,可以用來(lái)實(shí)現(xiàn)多種分布式協(xié)同機(jī)制。

znode 分類

一個(gè) znode 可以是持久性的螺句,也可以是臨時(shí)性的虽惭,znode 節(jié)點(diǎn)也可以是順序性的。每一個(gè)順序性的 znode 關(guān)聯(lián)一個(gè)唯一的單調(diào)遞增整數(shù)壹蔓,因此 ZooKeeper 主要有以下 4 種 znode:

  1. 持久性的 znode (PERSISTENT): ZooKeeper 宕機(jī)趟妥,或者 client 宕機(jī),這個(gè) znode 一旦創(chuàng)建就不會(huì)丟失佣蓉。
  2. 臨時(shí)性的 znode (EPHEMERAL): ZooKeeper 宕機(jī)了披摄,或者 client 在指定的 timeout 時(shí)間內(nèi)沒(méi)有連接 server,都會(huì)被認(rèn)為丟失勇凭。
  3. 持久順序性的 znode (PERSISTENT_SEQUENTIAL): znode 除了具備持久性 znode 的特點(diǎn)之外疚膊,znode 的名字具備順序性。
  4. 臨時(shí)順序性的 znode (EPHEMERAL_SEQUENTIAL): znode 除了具備臨時(shí)性 znode 的特點(diǎn)之外虾标,znode 的名字具備順序性寓盗。

安裝 ZooKeeper

https://archive.apache.org/dist/zookeeper/stable/ 下載 ZooKeeper,目前的最新版是 3.5.6璧函。

安裝ZooKeeper

把 apache-zookeeper-3.5.6-bin.tar.gz 解壓到一個(gè)本地目錄 (目錄名最好不要包含空格和中文)傀蚌。我使用 /usr/local 目錄。

tar -zxvf apache-zookeeper-3.5.6-bin.tar.gz

把 conf 目錄下的 zoo_sample.cfg 重命名為 zoo.cfg蘸吓,然后修改配置善炫。

# 心跳檢查的時(shí)間 2秒
tickTime=2000
# 初始化時(shí) 連接到服務(wù)器端的間隔次數(shù),總時(shí)間10*2=20秒
initLimit=10
# ZK Leader 和follower 之間通訊的次數(shù)库继,總時(shí)間5*2=10秒
syncLimit=5
# 存儲(chǔ)內(nèi)存中數(shù)據(jù)快照的位置箩艺,如果不設(shè)置參數(shù)窜醉,更新事務(wù)日志將被存儲(chǔ)到默認(rèn)位置。
dataDir=/data/zookeeper
# ZK 服務(wù)器端的監(jiān)聽(tīng)端口  
clientPort=2181

配置以下環(huán)境變量 vim /etc/profile

export ZOOKEEPER_HOME=/usr/local/apache-zookeeper-3.5.6-bin
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf

啟動(dòng) Zookeeper

再安裝配置完成后艺谆,就可以啟動(dòng) Zookeeper榨惰,使用 zkServer.sh start 啟動(dòng) ZooKeeper 服務(wù):

[root@wupx apache-zookeeper-3.5.6-bin]# zkServer.sh start
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/apache-zookeeper-3.5.6-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

檢查 ZooKeeper 日志是否有出錯(cuò)信息:

[root@wupx apache-zookeeper-3.5.6-bin]# cd logs/
[root@wupx logs]# grep -E -i "((exception)|(error))" *

因?yàn)榉祷貨](méi)有結(jié)果,說(shuō)明沒(méi)有錯(cuò)誤信息静汤。

檢查 ZooKeeper 數(shù)據(jù)文件琅催,這里存放的 ZooKeeper 的事務(wù)日志文件和快照日志文件。

[root@wupx zookeeper]# cd /data/zookeeper/
[root@wupx zookeeper]# tree
.
├── version-2
│   └── snapshot.0
└── zookeeper_server.pid
1 directory, 2 files

因?yàn)楝F(xiàn)在還沒(méi)有運(yùn)行任何 ZooKeeper 命令虫给,所以還沒(méi)有事務(wù)日志文件恢暖。

最后會(huì)檢查 ZooKeeper 是否在 2181 端口上監(jiān)聽(tīng)。

netstat -an | ag 2181

執(zhí)行后狰右,我們可以看到 ZooKeeper 已經(jīng)在 2181 這個(gè)端口上監(jiān)聽(tīng)了杰捂。

下面我們演示下如何使用 zkCli:

zkCli 使用

在執(zhí)行 zkCli.sh 命令后,會(huì)出現(xiàn)很多消息棋蚌,這些消息證明我們的 zkCli 和 ZooKeeper 的節(jié)點(diǎn)建立了有效連接嫁佳。

2019-12-22 10:38:36,684 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@959] - Socket connection established, initiating session, client: /127.0.0.1:54038, server: localhost/127.0.0.1:2181

使用 ls -R / 可以遞歸查找 ZooKeeper 的 znode 節(jié)點(diǎn),使用 create /znode_name 可以創(chuàng)建 znode 節(jié)點(diǎn)谷暮,具體演示如下:

# 使用 ls -R 可以遞歸查找 ZooKeeper 的 znode 節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 0] ls -R /
/
/zookeeper
/zookeeper/config
/zookeeper/quota
# 創(chuàng)建 znode /app1
[zk: localhost:2181(CONNECTED) 1] create /app1
Created /app1
[zk: localhost:2181(CONNECTED) 2] create /app2
Created /app2
[zk: localhost:2181(CONNECTED) 3] create /app1/p_1 1
Created /app1/p_1
[zk: localhost:2181(CONNECTED) 4] create /app1/p_2 2
Created /app1/p_2
[zk: localhost:2181(CONNECTED) 5] create /app1/p_3 3
Created /app1/p_3
[zk: localhost:2181(CONNECTED) 6] ls -R /
/
/app1
/app2
/zookeeper
/app1/p_1
/app1/p_2
/app1/p_3
/zookeeper/config
/zookeeper/quota

用 zkCli 實(shí)現(xiàn)鎖

分布式鎖要求如果鎖的持有者宕了蒿往,鎖可以被釋放。ZooKeeper 的 ephemeral 節(jié)點(diǎn)恰好具備這樣的特性湿弦。

接下來(lái)我們來(lái)演示下瓤漏,需要在兩個(gè)終端上分別啟動(dòng) zkCli,

在終端 1 上:

執(zhí)行 zkCli.sh颊埃,再執(zhí)行 create -e /lock 命令蔬充,來(lái)建立臨時(shí) znode,加鎖的操作其實(shí)就是建立 znode 的過(guò)程班利,此時(shí)第一個(gè)客戶端加鎖成功饥漫。

接下來(lái)嘗試在第二個(gè)客戶端加鎖,在終端 2 上:

執(zhí)行 zkCli.sh罗标,再執(zhí)行 create -e /lock 命令庸队,會(huì)發(fā)現(xiàn)提示 Node already exists: /lock,提示 znode 已存在闯割,znode 建立失敗彻消,因此加鎖失敗,這時(shí)候我們來(lái)監(jiān)控這個(gè) znode宙拉,使用 stat -w /lock 來(lái)等待鎖被釋放宾尚。

這個(gè)時(shí)候我們退出第一個(gè)客戶端,在終端 1 上執(zhí)行 quit 命令鼓黔,會(huì)在客戶端 2 上收到一條 WATCHER 信息央勒,具體如下:

WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/lock

再收到這個(gè)事件后再次在客戶端 2 上執(zhí)行加鎖,執(zhí)行 create -e /lock澳化,會(huì)顯示創(chuàng)建 znode 成功崔步,即加鎖成功。

總結(jié)

這篇文章主要介紹了 ZooKeeper 的安裝配置缎谷,ZooKeeper 的基本概念和 zkCli 的使用井濒,并用 zkCli 來(lái)實(shí)現(xiàn)一個(gè)鎖,為后面更加深入的學(xué)習(xí)打好基礎(chǔ)列林。

參考

https://zookeeper.apache.org/doc/current/zookeeperOver.html

https://zookeeper.apache.org/doc/current/zookeeperStarted.html

《從Paxos到Zookeeper:分布式一致性原理與實(shí)踐》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瑞你,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子希痴,更是在濱河造成了極大的恐慌者甲,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砌创,死亡現(xiàn)場(chǎng)離奇詭異虏缸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嫩实,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)刽辙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人甲献,你說(shuō)我怎么就攤上這事宰缤。” “怎么了晃洒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵慨灭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我球及,道長(zhǎng)缘挑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任桶略,我火速辦了婚禮语淘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘际歼。我一直安慰自己惶翻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布鹅心。 她就那樣靜靜地躺著吕粗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旭愧。 梳的紋絲不亂的頭發(fā)上颅筋,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天宙暇,我揣著相機(jī)與錄音,去河邊找鬼议泵。 笑死占贫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的先口。 我是一名探鬼主播型奥,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碉京!你這毒婦竟也來(lái)了厢汹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谐宙,失蹤者是張志新(化名)和其女友劉穎烫葬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凡蜻,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厘灼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咽瓷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片设凹。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茅姜,靈堂內(nèi)的尸體忽然破棺而出闪朱,到底是詐尸還是另有隱情,我是刑警寧澤钻洒,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布奋姿,位于F島的核電站,受9級(jí)特大地震影響素标,放射性物質(zhì)發(fā)生泄漏称诗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一头遭、第九天 我趴在偏房一處隱蔽的房頂上張望寓免。 院中可真熱鬧,春花似錦计维、人聲如沸袜香。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蜈首。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間欢策,已是汗流浹背吆寨。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踩寇,地道東北人啄清。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姑荷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缩擂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容