三、ZooKeeper的典型應(yīng)用場景

ZooKeeper是一個典型的發(fā)布/訂閱模式的分布式數(shù)據(jù)管理與協(xié)調(diào)框架,開發(fā)人員可以使用它來進(jìn)行分布式數(shù)據(jù)的發(fā)布與訂閱。另一方面,通過對ZooKeeper中豐富的數(shù)據(jù)節(jié)點(diǎn)類型進(jìn)行交叉使用,配合Watcher事件通知機(jī)制,可以非常方便的構(gòu)建一系列分布式應(yīng)用中都會涉及的核心功能,如數(shù)據(jù)發(fā)布/訂閱、負(fù)載均衡、命名服務(wù)、分布式協(xié)調(diào)/通知、集群管理、Master選舉、分布式鎖和分布式隊(duì)列等。

一、典型應(yīng)用場景及實(shí)現(xiàn)

1.1 數(shù)據(jù)發(fā)布/訂閱

數(shù)據(jù)發(fā)布/訂閱(Publish/Subscribe)系統(tǒng),即所謂的配置中心,顧名思義就是發(fā)布者jiang將數(shù)據(jù)發(fā)布到ZooKeeper的一個或一系列節(jié)點(diǎn)上,供訂閱者進(jìn)行數(shù)據(jù)訂閱,進(jìn)而達(dá)到動態(tài)獲取數(shù)據(jù)的目的,實(shí)現(xiàn)配置信息的集中式管理和數(shù)據(jù)的動態(tài)更新。

發(fā)布/訂閱系統(tǒng)一般有兩種設(shè)計模式,分別是推(Push)模式和拉(Pull)模式。

  • 推模式

服務(wù)端主動將數(shù)據(jù)更新發(fā)送給所有訂閱的客戶端。

  • 拉模式

客戶端通過采用定時輪詢拉取。

ZooKeeper采用的是推拉相結(jié)合的方式:客戶端向服務(wù)端注冊自己需要關(guān)注的節(jié)點(diǎn),一旦該節(jié)點(diǎn)的數(shù)據(jù)發(fā)生變更,那么服務(wù)端就會向相應(yīng)的客戶端發(fā)送Watcher事件通知,客戶端接收到這個消息通知之后,需要主動到服務(wù)端獲取最新的數(shù)據(jù)。

1.2 負(fù)載均衡

根據(jù)維基百科的定義,負(fù)載均衡(Load Balance)是一種相當(dāng)常見的計算機(jī)網(wǎng)絡(luò)技術(shù),用來對多個計算機(jī)(計算機(jī)集群)、網(wǎng)絡(luò)連接、CPU、硬盤驅(qū)動器或其他資源進(jìn)行分配負(fù)載,以達(dá)到優(yōu)化資源使用、最大化吞吐率、最小化響應(yīng)時間和避免過載的目的。通常,負(fù)載均衡可以分為硬件和軟件負(fù)載均衡兩類。

1.3 命名服務(wù)

命名服務(wù)(Name Service)也是分布式系統(tǒng)中比較常見的一類場景。在《Java網(wǎng)絡(luò)高級編程》一書中提到,命名服務(wù)是分布式系統(tǒng)最基本的公共服務(wù)之一。在分布式系統(tǒng)中,被命名的實(shí)體通常是集群中的機(jī)器、提供的服務(wù)地址或遠(yuǎn)程對象等--這些我們都可以統(tǒng)稱他們?yōu)槊郑渲斜容^常見的就是一些分布式服務(wù)框架(RPC、RMI)中的服務(wù)地址列表,通過使用命名服務(wù),客戶端應(yīng)用能夠根據(jù)指定名字來獲取資源的實(shí)體、服務(wù)地址和提供者信息等。

Java語言中的JNDI便是一種典型的命名服務(wù)。JNDI是Java命名和目錄接口(Java Naming and Directory Interface)的縮寫,是J2EE體系中重要的規(guī)范之一,標(biāo)準(zhǔn)的J2EE容器都提供了對JNDI規(guī)范的實(shí)現(xiàn)。因此,在實(shí)際開發(fā)中,開發(fā)人員常常使用應(yīng)用服務(wù)器自帶的JNDI實(shí)現(xiàn)來完成數(shù)據(jù)源的配置與管理--使用JNDI方式后,開發(fā)人員可以完全不需要關(guān)心與數(shù)據(jù)庫相關(guān)的任何信息,包括數(shù)據(jù)庫類型、JDBC驅(qū)動類型以及數(shù)據(jù)庫賬戶等。

ZooKeeper提供的命名服務(wù)功能與JNDI技術(shù)有類似的地方,都能夠幫助應(yīng)用系統(tǒng)通過一個資源引用的方式來實(shí)現(xiàn)對資源的定位與使用。另外,廣義上命名服務(wù)的資源定位都不是真正意義的實(shí)體資源--在分布式環(huán)境中,上層應(yīng)用僅僅需要一個全局唯一的名字,類似于數(shù)據(jù)庫的唯一主鍵。下面我們看看如何使用ZooKeeper來實(shí)現(xiàn)一套分布式全局唯一ID的分配機(jī)制。

所謂ID,就是一個能唯一標(biāo)識某個對象的標(biāo)識符。一說起全局唯一ID,相信讀者都會聯(lián)想到UUID。UUID是通用唯一標(biāo)識碼(Universally Unique Identifier)的簡稱,是一種在分布式系統(tǒng)中廣泛使用的用于唯一標(biāo)識元素的標(biāo)準(zhǔn),最典型的實(shí)現(xiàn)是GUID(Globally Unique Identifier,全局唯一標(biāo)識符),主流ORM框架Hibernate有對UUID的直接支持。

一個標(biāo)準(zhǔn)的UUID是一個包含32位字符和4各短線的字符串。他的優(yōu)勢自然不必多說,我們來看看他的缺陷。

  • 長度過長

和數(shù)據(jù)庫中的INT類型相比,存儲一個UUID需要花費(fèi)更多的空間。

  • 含義不明

根據(jù)字面完全看不出任何含義,這會大大影響問題排查和開發(fā)調(diào)試的效率。

接下來我們來講解使用ZooKeeper生成唯一ID的基本步驟。

  • 所有客戶端都會根據(jù)自己的任務(wù)類型,在指定類型的任務(wù)下面通過調(diào)用create()接口來創(chuàng)建一個順序節(jié)點(diǎn),例如創(chuàng)建“job-”節(jié)點(diǎn)。
  • 節(jié)點(diǎn)創(chuàng)建完畢后,create()接口會返回一個完整的節(jié)點(diǎn)名,例如“job-0000000003”。
  • 客戶端拿到這個返回值后,拼接上type類型,例如“type2-job-0000000003”,這樣就可以作為一個全局唯一的ID了。

1.4 分布式協(xié)調(diào)/通知

分布式協(xié)調(diào)/通知是將不同的分布式組件有機(jī)結(jié)合起來的關(guān)鍵所在。對于一個在多臺機(jī)器上部署運(yùn)行的應(yīng)用而言,通常需要一個協(xié)調(diào)者(Coordinator)來控制整個系統(tǒng)的運(yùn)行流程,例如分布式事務(wù)的處理、機(jī)器間的相互協(xié)調(diào)等。同時,引入這樣一個協(xié)調(diào)者,便于將分布式協(xié)調(diào)的職責(zé)從應(yīng)用中分離出來,從而大大減少系統(tǒng)之家的耦合性,而且能夠顯著提高系統(tǒng)的可擴(kuò)展性。

ZooKeeper中特有的Watcher注冊于異步通知機(jī)制,能夠很好地實(shí)現(xiàn)分布式環(huán)境下不同機(jī)器,甚至是不同系統(tǒng)之間的協(xié)調(diào)與通知,從而實(shí)現(xiàn)對數(shù)據(jù)變更的實(shí)時處理。基于ZooKeeper實(shí)現(xiàn)分布式協(xié)調(diào)與通知功能,通常的做法是不同的客戶端都對ZooKeeper上同一數(shù)據(jù)節(jié)點(diǎn)進(jìn)行Watcher注冊,監(jiān)聽數(shù)據(jù)節(jié)點(diǎn)的變化(包括數(shù)據(jù)節(jié)點(diǎn)本身及其子節(jié)點(diǎn)),如果數(shù)據(jù)節(jié)點(diǎn)發(fā)生變化,那么所有訂閱的客戶端都能接收到相應(yīng)的Watcher通知,并作出相應(yīng)的處理。

一種通用的分布式系統(tǒng)機(jī)器間通信方式

心跳檢測

機(jī)器間的心跳檢測機(jī)制是指在分布式環(huán)境中,不同機(jī)器之間需要檢測到彼此是否在正常運(yùn)行。在傳統(tǒng)的開發(fā)中,我們通常是通過主機(jī)之間是否可以相互PING通來判斷,更復(fù)雜一點(diǎn)的話,則會通過在機(jī)器之間建立長連接,通過TCP連接固有的心跳檢測機(jī)制來實(shí)現(xiàn)上層機(jī)器的心跳檢測。

下面看看如何使用ZooKeeper來實(shí)現(xiàn)分布式機(jī)器間的心跳檢測。基于ZooKeeper的臨時節(jié)點(diǎn)特性,可以讓不同的機(jī)器都在ZooKeeper的一個指定節(jié)點(diǎn)下創(chuàng)建臨時子節(jié)點(diǎn),不同的機(jī)器之間可以根據(jù)這個臨時節(jié)點(diǎn)來判斷對應(yīng)的客戶端機(jī)器是否存活。通過這種方式,檢測系統(tǒng)和被檢測系統(tǒng)間并不需要直接相關(guān)聯(lián),而是通過ZooKeeper上的某個節(jié)點(diǎn)進(jìn)行關(guān)聯(lián),大大減少了系統(tǒng)耦合。

工作進(jìn)度匯報

系統(tǒng)調(diào)度

后臺管理人員操作控制臺,實(shí)際上修改ZooKeeper某些節(jié)點(diǎn)的數(shù)據(jù),然后ZooKeeper把這些數(shù)據(jù)變更以事件通知的形式發(fā)送給了對應(yīng)的訂閱客戶端。

1.5 集群管理

1.6 Master選舉

1.7 分布式鎖

1.8 分布式隊(duì)列

二、ZooKeeper在大型分布式系統(tǒng)中的應(yīng)用

2.1 Hadoop

在Hadoop中,ZooKeeper主要用于實(shí)現(xiàn)HA(High Availability),這部分邏輯主要集中在Hadoop Common的HA模塊中,HDFS的NameNode與YARN的ResouceManager都是基于此HA模塊來實(shí)現(xiàn)自己的HA功能的。同時,在YARN中又特別提供了ZooKeeper來存儲應(yīng)用的運(yùn)行狀態(tài)。

2.2 HBase

HBase,全程Hadoop Database,是Google Bigtable的開源實(shí)現(xiàn),是一個基于Hadoop文件系統(tǒng)設(shè)計的面向海量數(shù)據(jù)的高可靠性、高性能、面向列、可伸縮的分布式存儲系統(tǒng),利用HBase技術(shù)可以在廉價的PC服務(wù)器上搭建起大規(guī)模結(jié)構(gòu)化的存儲集群。

HBase在實(shí)現(xiàn)上嚴(yán)格遵守了Google BigTable論文的設(shè)計思想。BigTable使用Chubby來負(fù)責(zé)分布式狀態(tài)的協(xié)調(diào),這是Google實(shí)現(xiàn)的一種基于Paxos算法的分布式鎖服務(wù),而HBase則采用了開源的ZooKeeper服務(wù)來完成對整個系統(tǒng)的分布式協(xié)調(diào)工作。

2.3 Kafka

Kafka是一個吞吐量極高的分布式消息系統(tǒng),其整體設(shè)計師典型的發(fā)布與訂閱模式系統(tǒng)。在Kafka集群中,沒有“中心主節(jié)點(diǎn)”的概念,集群中所有的服務(wù)器都是對等的,因此可以在不做任何配置更改的情況下實(shí)現(xiàn)服務(wù)器的添加和刪除,同樣,消息的生產(chǎn)者和消費(fèi)者也能做到隨意重啟和機(jī)器的上下線。在Kafka的設(shè)計中,選擇使用ZooKeeper來進(jìn)行所有Broker的管理。

Kafka使用ZooKeeper作為其分布式協(xié)調(diào)框架,很好地將消息生成、消息存儲和消息消費(fèi)有機(jī)結(jié)合起來,同時借助ZooKeeper,Kafka能在保持包括生產(chǎn)者、消費(fèi)者和Broker在內(nèi)的所有組件無狀態(tài)的情況下,建立起生產(chǎn)者和消費(fèi)者之間的訂閱關(guān)系,并實(shí)現(xiàn)了生產(chǎn)者和消費(fèi)者的負(fù)載均衡。

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

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