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

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

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

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

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

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

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

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

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

LOOKING:當前Server不知道leader是誰,正在搜尋。

LEADING:當前Server即為選舉出來的leader。

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


  ZooKeeper的安裝模式分為三種,分別為:單機模式、集群模式和集群偽分布模式

環(huán)境

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

  ZooKeeper最新版本

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

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

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

下載

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

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

安裝

單機模式

  進入zookeeper目錄下的conf子目錄, 重命名 zoo_sample.cfg文件,Zookeeper 在啟動時會找這個文件作為默認配置文件:

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ù)說明:

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

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

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

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

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

mkdir? /usr/local/zookeeper/data

mkdir? /usr/local/zookeeper/log

啟動zookeeper

  先進入/usr/local/zookeeper文件夾

cd /usr/local/zookeeper

  再運行?

bin/zkServer.sh start

  檢測是否成功啟動:執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181


?偽集群模式

所謂偽集群, 是指在單臺機器中啟動多個zookeeper進程, 并組成一個集群. 以啟動3個zookeeper進程為例,模擬3臺機。

將zookeeper的目錄多拷貝2份:

zookeeper/conf/zoo.cfg文件與單機一樣,只改為下面的內(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

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

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

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

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

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

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

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

  分別進入/usr/local/zookeeper/bin, /usr/local/zookeeper1/bin, /usr/local/zookeeper2/bin三個目錄, 啟動server。啟動方法與單機一致。

bin/zkServer.sh start

  分別檢測是否成功啟動:執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181


集群模式

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

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

下面是一個示例:

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臺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

  分別進入/usr/local/zookeeper/bin目錄, 啟動server。啟動方法與單機一致。

bin/zkServer.sh start

  分別檢測是否成功啟動:執(zhí)行

bin/zkCli.sh

echo stat|nc localhost 2181

?  這時會報大量錯誤?其實沒什么關(guān)系,因為現(xiàn)在集群只起了1臺server,zookeeper服務(wù)器端起來會根據(jù)zoo.cfg的服務(wù)器列表發(fā)起選舉leader的請求,因為連不上其他機器而報錯,那么當我們起第二個zookeeper實例后,leader將會被選出,從而一致性服務(wù)開始可以使用,這是因為3臺機器只要有2臺可用就可以選出leader并且對外提供服務(wù)(2n+1臺機器,可以容n臺機器掛掉)。


ZooKeeper服務(wù)命令

1. 啟動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)境,使用它可以對ZooKeeper進行訪問,數(shù)據(jù)創(chuàng)建,數(shù)據(jù)修改等操作.

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

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

?擴展

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

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

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

(1)? ???每個節(jié)點在zookeeper中叫做znode,并且其有一個唯一的路徑標識,如/SERVER2節(jié)點的標識就為/APP3/SERVER2

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

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

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

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

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

?選舉流程

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

basic paxos流程:

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

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

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

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

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

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

應(yīng)用場景

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

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

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

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

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

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


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容