一步到位分布式開發(fā)Zookeeper實(shí)現(xiàn)集群管理

https://www.cnblogs.com/zhangs1986/p/6564839.html?from=timeline

說(shuō)到分布式開發(fā)Zookeeper是必須了解和掌握的,分布式消息服務(wù)kafka 、hbase 到hadoop等分布式大數(shù)據(jù)處理都會(huì)用到Zookeeper,所以在此將Zookeeper作為基礎(chǔ)來(lái)講解。

?  Zookeeper 是分布式服務(wù)框架,主要是用來(lái)解決分布式應(yīng)用中經(jīng)常遇到的一些數(shù)據(jù)管理問(wèn)題,如:統(tǒng)一命名服務(wù)、狀態(tài)同步服務(wù)、集群管理、分布式應(yīng)用配置項(xiàng)的管理等等。

Zookeeper 的核心是廣播,這個(gè)機(jī)制保證了各個(gè)Server之間的同步。實(shí)現(xiàn)這個(gè)機(jī)制的協(xié)議叫做Zab協(xié)議。

Zab協(xié)議有兩種模式,它們分別是恢復(fù)模式(選主)和廣播 模式(同步)。當(dāng)服務(wù)啟動(dòng)或者在領(lǐng)導(dǎo)者崩潰后,Zab就進(jìn)入了恢復(fù)模式,當(dāng)領(lǐng)導(dǎo)者被選舉出來(lái),且大多數(shù)Server完成了和leader的狀態(tài)同步以后, 恢復(fù)模式就結(jié)束了。

狀態(tài)同步保證了leader和Server具有相同的系統(tǒng)狀態(tài)。為了保證事務(wù)的順序一致性,zookeeper采用了遞增的事務(wù)id號(hào) (zxid)來(lái)標(biāo)識(shí)事務(wù)。

所有的提議(proposal)都在被提出的時(shí)候加上了zxid。實(shí)現(xiàn)中zxid是一個(gè)64位的數(shù)字,它高32位是epoch用 來(lái)標(biāo)識(shí)leader關(guān)系是否改變,每次一個(gè)leader被選出來(lái),它都會(huì)有一個(gè)新的epoch,標(biāo)識(shí)當(dāng)前屬于那個(gè)leader的統(tǒng)治時(shí)期。低32位用于遞 增計(jì)數(shù)。

每個(gè)Server在工作過(guò)程中有三種狀態(tài):

LOOKING:當(dāng)前Server不知道leader是誰(shuí),正在搜尋。

LEADING:當(dāng)前Server即為選舉出來(lái)的leader。

FOLLOWING:leader已經(jīng)選舉出來(lái),當(dāng)前Server與之同步。


  ZooKeeper的安裝模式分為三種,分別為:?jiǎn)螜C(jī)模式、集群模式和集群偽分布模式

環(huán)境

  CentOS7.0 ?(windows中使用就使用zkServer.cmd)

  ZooKeeper最新版本

  用root用戶安裝(如果用于hbase時(shí)將所有文件權(quán)限改為hadoop用戶)

? ? ?Java環(huán)境,最好是最新版本的。

分布式時(shí)多機(jī)間要確保能正常通訊,關(guān)閉防火墻或讓涉及到的端口通過(guò)。

下載

  去官網(wǎng)下載 :http://zookeeper.apache.org/releases.html#download

  下載后放進(jìn)CentOS中的/usr/local/ 文件夾中,并解壓到當(dāng)前文件中 /usr/local/zookeeper(怎么解壓可參考之前的Haproxy的安裝文章)

安裝

單機(jī)模式

  進(jìn)入zookeeper目錄下的conf子目錄, 重命名 zoo_sample.cfg文件,Zookeeper 在啟動(dòng)時(shí)會(huì)找這個(gè)文件作為默認(rèn)配置文件:

mv /usr/local/zookeeper/conf/zoo_sample.cfg ?zoo.cfg

  配置zoo.cfg參數(shù)

# The number of milliseconds of each ticktickTime=2000# The number of ticks that the initial # synchronization phase can takeinitLimit=10# The number of ticks that can pass between # sending a request and getting an acknowledgementsyncLimit=5# the directory where the snapshot is stored.# do not use /tmp for storage, /tmp here is just # example sakes.dataDir=/usr/local/zookeeper/data

dataLogDir=/usr/local/zookeeper/log# the port at which the clients will connectclientPort=2181#

# Be sure to read the maintenance section of the # administrator guide before turning on autopurge.#

#http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance#

# The number of snapshots to retain in dataDir#autopurge.snapRetainCount=3# Purge task interval in hours# Set to "0" to disable auto purge feature#autopurge.purgeInterval=1

參數(shù)說(shuō)明:

tickTime:毫秒值.這個(gè)時(shí)間是作為 Zookeeper 服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔,也就是每個(gè) tickTime 時(shí)間就會(huì)發(fā)送一個(gè)心跳。

dataDir:顧名思義就是 Zookeeper 保存數(shù)據(jù)的目錄,默認(rèn)情況下,Zookeeper 將寫數(shù)據(jù)的日志文件也保存在這個(gè)目錄里。

dataLogDir:顧名思義就是 Zookeeper 保存日志文件的目錄

clientPort:這個(gè)端口就是客戶端連接 Zookeeper 服務(wù)器的端口,Zookeeper 會(huì)監(jiān)聽這個(gè)端口,接受客戶端的訪問(wèn)請(qǐng)求。

  再創(chuàng)建上面配置的data和log文件夾:

mkdir? /usr/local/zookeeper/data

mkdir? /usr/local/zookeeper/log

啟動(dòng)zookeeper

  先進(jìn)入/usr/local/zookeeper文件夾

cd /usr/local/zookeeper

  再運(yùn)行?

bin/zkServer.sh start

  檢測(cè)是否成功啟動(dòng):執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181


?偽集群模式

所謂偽集群, 是指在單臺(tái)機(jī)器中啟動(dòng)多個(gè)zookeeper進(jìn)程, 并組成一個(gè)集群. 以啟動(dòng)3個(gè)zookeeper進(jìn)程為例,模擬3臺(tái)機(jī)。

將zookeeper的目錄多拷貝2份:

zookeeper/conf/zoo.cfg文件與單機(jī)一樣,只改為下面的內(nèi)容:

tickTime=2000

initLimit=5

syncLimit=2

dataDir=/usr/local/zookeeper/data

dataLogDir=/usr/local/zookeeper/log

clientPort=2180server.0=127.0.0.1:2888:3888server.1=127.0.0.1:2889:3889

server.2=127.0.0.1:2890:3890

  新增了幾個(gè)參數(shù), 其含義如下:

1 initLimit: zookeeper集群中的包含多臺(tái)server, 其中一臺(tái)為leader, 集群中其余的server為follower. initLimit參數(shù)配置初始化連接時(shí), follower和leader之間的最長(zhǎng)心跳時(shí)間. 此時(shí)該參數(shù)設(shè)置為5, 說(shuō)明時(shí)間限制為5倍tickTime, 即5*2000=10000ms=10s.

2 syncLimit: 該參數(shù)配置leader和follower之間發(fā)送消息, 請(qǐng)求和應(yīng)答的最大時(shí)間長(zhǎng)度. 此時(shí)該參數(shù)設(shè)置為2, 說(shuō)明時(shí)間限制為2倍tickTime, 即4000ms.

3 server.X=A:B:C 其中X是一個(gè)數(shù)字, 表示這是第幾號(hào)server. A是該server所在的IP地址. B配置該server和集群中的leader交換消息所使用的端口. C配置選舉leader時(shí)所使用的端口. 由于配置的是偽集群模式, 所以各個(gè)server的B, C參數(shù)必須不同.

參照zookeeper/conf/zoo.cfg, 配置zookeeper1/conf/zoo.cfg, 和zookeeper2/conf/zoo.cfg文件. 只需更改dataDir, dataLogDir, clientPort參數(shù)即可.

在之前設(shè)置的dataDir中新建myid文件, 寫入一個(gè)數(shù)字, 該數(shù)字表示這是第幾號(hào)server. 該數(shù)字必須和zoo.cfg文件中的server.X中的X一一對(duì)應(yīng).

/usr/local/zookeeper/data/myid文件中寫入0, /usr/local/zookeeper1/data/myid文件中寫入1, /Users/apple/zookeeper2/data/myid文件中寫入2.

  分別進(jìn)入/usr/local/zookeeper/bin, /usr/local/zookeeper1/bin, /usr/local/zookeeper2/bin三個(gè)目錄, 啟動(dòng)server。啟動(dòng)方法與單機(jī)一致。

bin/zkServer.sh start

  分別檢測(cè)是否成功啟動(dòng):執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181


集群模式

集群模式的配置和偽集群基本一致.

由于集群模式下, 各server部署在不同的機(jī)器上, 因此各server的conf/zoo.cfg文件可以完全一樣.

下面是一個(gè)示例:

tickTime=2000

initLimit=5

syncLimit=2

dataDir=/usr/local/zookeeper/data

dataLogDir=/usr/local/zookeeper/log

clientPort=2180server.0=192.168.80.30:2888:3888server.1=192.168.80.31:2888:3888server.2=192.168.80.32:2888:3888

  示例中部署了3臺(tái)zookeeper server, 分別部署在192.168.80.30, 192.168.80.31, 192.168.80.32上.?

需要注意的是, 各server的dataDir目錄下的myid文件中的數(shù)字必須不同,192.168.80.30 server的myid為0, 192.168.80.31 server的myid為1, 192.168.80.32 server的myid為2

  分別進(jìn)入/usr/local/zookeeper/bin目錄, 啟動(dòng)server。啟動(dòng)方法與單機(jī)一致。

bin/zkServer.sh start

  分別檢測(cè)是否成功啟動(dòng):執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181

?  這時(shí)會(huì)報(bào)大量錯(cuò)誤?其實(shí)沒(méi)什么關(guān)系,因?yàn)楝F(xiàn)在集群只起了1臺(tái)server,zookeeper服務(wù)器端起來(lái)會(huì)根據(jù)zoo.cfg的服務(wù)器列表發(fā)起選舉leader的請(qǐng)求,因?yàn)檫B不上其他機(jī)器而報(bào)錯(cuò),那么當(dāng)我們起第二個(gè)zookeeper實(shí)例后,leader將會(huì)被選出,從而一致性服務(wù)開始可以使用,這是因?yàn)?臺(tái)機(jī)器只要有2臺(tái)可用就可以選出leader并且對(duì)外提供服務(wù)(2n+1臺(tái)機(jī)器,可以容n臺(tái)機(jī)器掛掉)。


ZooKeeper服務(wù)命令

1. 啟動(dòng)ZK服務(wù): zkServer.sh start2. 查看ZK服務(wù)狀態(tài): zkServer.sh status3. 停止ZK服務(wù): zkServer.sh stop4. 重啟ZK服務(wù): zkServer.sh restart


zk客戶端命令:

  ZooKeeper 命令行工具類似于Linux的shell環(huán)境,使用它可以對(duì)ZooKeeper進(jìn)行訪問(wèn),數(shù)據(jù)創(chuàng)建,數(shù)據(jù)修改等操作.

  使用 zkCli.sh -server 192.168.80.31:2181 連接到 ZooKeeper 服務(wù),連接成功后,系統(tǒng)會(huì)輸出 ZooKeeper 的相關(guān)環(huán)境以及配置信息。命令行工具的一些簡(jiǎn)單操作如下:

1. 顯示根目錄下、文件: ls / 使用 ls 命令來(lái)查看當(dāng)前 ZooKeeper 中所包含的內(nèi)容2. 顯示根目錄下、文件: ls2 / 查看當(dāng)前節(jié)點(diǎn)數(shù)據(jù)并能看到更新次數(shù)等數(shù)據(jù)3. 創(chuàng)建文件,并設(shè)置初始內(nèi)容: create /zk"test" 創(chuàng)建一個(gè)新的 znode節(jié)點(diǎn)“ zk ”以及與它關(guān)聯(lián)的字符串4. 獲取文件內(nèi)容: get /zk 確認(rèn) znode 是否包含我們所創(chuàng)建的字符串5. 修改文件內(nèi)容: set /zk"zkbak" 對(duì) zk 所關(guān)聯(lián)的字符串進(jìn)行設(shè)置6. 刪除文件: delete /zk 將剛才創(chuàng)建的 znode 刪除7. 退出客戶端: quit8. 幫助命令: help

?擴(kuò)展

  通過(guò)上述命令實(shí)踐,我們可以發(fā)現(xiàn),zookeeper使用了一個(gè)類似文件系統(tǒng)的樹結(jié)構(gòu),數(shù)據(jù)可以掛在某個(gè)節(jié)點(diǎn)上,可以對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行刪改。另外我們還發(fā)現(xiàn),當(dāng)改動(dòng)一個(gè)節(jié)點(diǎn)的時(shí)候,集群中活著的機(jī)器都會(huì)更新到一致的數(shù)據(jù)。?

zookeeper的數(shù)據(jù)模型

在簡(jiǎn)單使用了zookeeper之后,我們發(fā)現(xiàn)其數(shù)據(jù)模型有些像操作系統(tǒng)的文件結(jié)構(gòu),結(jié)構(gòu)如下圖所示

(1)? ???每個(gè)節(jié)點(diǎn)在zookeeper中叫做znode,并且其有一個(gè)唯一的路徑標(biāo)識(shí),如/SERVER2節(jié)點(diǎn)的標(biāo)識(shí)就為/APP3/SERVER2

(2)? ???Znode可以有子znode,并且znode里可以存數(shù)據(jù),但是EPHEMERAL類型的節(jié)點(diǎn)不能有子節(jié)點(diǎn)

(3)? ???Znode中的數(shù)據(jù)可以有多個(gè)版本,比如某一個(gè)路徑下存有多個(gè)數(shù)據(jù)版本,那么查詢這個(gè)路徑下的數(shù)據(jù)就需要帶上版本。

(4)? ???znode 可以是臨時(shí)節(jié)點(diǎn),一旦創(chuàng)建這個(gè) znode 的客戶端與服務(wù)器失去聯(lián)系,這個(gè) znode 也將自動(dòng)刪除,Zookeeper 的客戶端和服務(wù)器通信采用長(zhǎng)連接方式,每個(gè)客戶端和??服務(wù)器通過(guò)心跳來(lái)保持連接,這個(gè)連接狀態(tài)稱為 session,如果 znode 是臨時(shí)節(jié)點(diǎn),這個(gè) session 失效,znode 也就刪除了

(5)? ???znode 的目錄名可以自動(dòng)編號(hào),如 App1 已經(jīng)存在,再創(chuàng)建的話,將會(huì)自動(dòng)命名為 App2

(6)? ???znode 可以被監(jiān)控,包括這個(gè)目錄節(jié)點(diǎn)中存儲(chǔ)的數(shù)據(jù)的修改,子節(jié)點(diǎn)目錄的變化等,一旦變化可以通知設(shè)置監(jiān)控的客戶端,這個(gè)功能是zookeeper對(duì)于應(yīng)用最重要的特性,通過(guò)這個(gè)特性可以實(shí)現(xiàn)的功能包括配置的集中管理,集群管理,分布式鎖等等。

?選舉流程

當(dāng) leader崩潰或者leader失去大多數(shù)的follower,這時(shí)候zk進(jìn)入恢復(fù)模式,恢復(fù)模式需要重新選舉出一個(gè)新的leader,讓所有的 Server都恢復(fù)到一個(gè)正確的狀態(tài)。Zk的選舉算法有兩種:一種是基于basic paxos實(shí)現(xiàn)的,另外一種是基于fast paxos算法實(shí)現(xiàn)的。系統(tǒng)默認(rèn)的選舉算法為fast paxos。

basic paxos流程:

1 .選舉線程由當(dāng)前Server發(fā)起選舉的線程擔(dān)任,其主要功能是對(duì)投票結(jié)果進(jìn)行統(tǒng)計(jì),并選出推薦的Server;

2 .選舉線程首先向所有Server發(fā)起一次詢問(wèn)(包括自己);

3 .選舉線程收到回復(fù)后,驗(yàn)證是否是自己發(fā)起的詢問(wèn)(驗(yàn)證zxid是否一致),然后獲取對(duì)方的id(myid),并存儲(chǔ)到當(dāng)前詢問(wèn)對(duì)象列表中,最后獲取對(duì)方提議的leader相關(guān)信息(id,zxid),并將這些信息存儲(chǔ)到當(dāng)次選舉的投票記錄表中;

4. 收到所有Server回復(fù)以后,就計(jì)算出zxid最大的那個(gè)Server,并將這個(gè)Server相關(guān)信息設(shè)置成下一次要投票的Server;

5. 線程將當(dāng)前zxid最大的Server設(shè)置為當(dāng)前Server要推薦的Leader,如果此時(shí)獲勝的Server獲得n/2 + 1的Server票數(shù), 設(shè)置當(dāng)前推薦的leader為獲勝的Server,將根據(jù)獲勝的Server相關(guān)信息設(shè)置自己的狀態(tài),否則,繼續(xù)這個(gè)過(guò)程,直到leader被選舉出來(lái)。

通 過(guò)流程分析我們可以得出:要使Leader獲得多數(shù)Server的支持,則Server總數(shù)必須是奇數(shù)2n+1,且存活的Server的數(shù)目不得少于 n+1.每個(gè)Server啟動(dòng)后都會(huì)重復(fù)以上流程。在恢復(fù)模式下,如果是剛從崩潰狀態(tài)恢復(fù)的或者剛啟動(dòng)的server還會(huì)從磁盤快照中恢復(fù)數(shù)據(jù)和會(huì)話信 息,zk會(huì)記錄事務(wù)日志并定期進(jìn)行快照,方便在恢復(fù)時(shí)進(jìn)行狀態(tài)恢復(fù)。

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

?  是指通過(guò)指定的名字來(lái)獲取資源或者服務(wù)的地址,提供者的信息。利用Zookeeper很容易創(chuàng)建一個(gè)全局的路徑,而這個(gè)路徑就可以作為一個(gè)名字,它可以指向集群中的集群,提供的服務(wù)的地址,遠(yuǎn)程對(duì)象等。簡(jiǎn)單來(lái)說(shuō)使用Zookeeper做命名服務(wù)就是用路徑作為名字,路徑上的數(shù)據(jù)就是其名字指向的實(shí)體。

  阿里巴巴集團(tuán)開源的分布式服務(wù)框架Dubbo中使用ZooKeeper來(lái)作為其命名服務(wù),維護(hù)全局的服務(wù)地址列表。在Dubbo實(shí)現(xiàn)中:

服務(wù)提供者在啟動(dòng)的時(shí)候,向ZK上的指定節(jié)點(diǎn)/dubbo/${serviceName}/providers目錄下寫入自己的URL地址,這個(gè)操作就完成了服務(wù)的發(fā)布。

服務(wù)消費(fèi)者啟動(dòng)的時(shí)候,訂閱/dubbo/{serviceName}/providers目錄下的提供者URL地址, 并向/dubbo/{serviceName} /consumers目錄下寫入自己的URL地址。

  注意,所有向ZK上注冊(cè)的地址都是臨時(shí)節(jié)點(diǎn),這樣就能夠保證服務(wù)提供者和消費(fèi)者能夠自動(dòng)感應(yīng)資源的變化。

  另外,Dubbo還有針對(duì)服務(wù)粒度的監(jiān)控,方法是訂閱/dubbo/{serviceName}目錄下所有提供者和消費(fèi)者的信息。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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