Zookeeper 集群部署的那些事兒
本文轉(zhuǎn)載自微信公眾號「牧小農(nóng)」,作者牧小農(nóng)。轉(zhuǎn)載本文請聯(lián)系牧小農(nóng)公眾號。
簡介
額。。。。, &*$% 淘氣!
ZooKeeper 是 Apache 的一個頂級項目,為分布式應(yīng)用提供高效、高可用的分布式協(xié)調(diào)服務(wù)。
ZooKeeper本質(zhì)上是一個分布式的小文件存儲系統(tǒng)。提供類似于文件系統(tǒng)目錄樹方式的數(shù)據(jù)存儲,并且可以對書中的節(jié)點進行有效管理。從而用來維護和監(jiān)控存儲的數(shù)據(jù)的狀態(tài)變化,通過監(jiān)控這些數(shù)據(jù)狀態(tài)的變化,實現(xiàn)基于數(shù)據(jù)的集群管理。
運行模式
ZooKeeper 運行模式有三種:單機模式、偽集群模式、集群模式
單機模式: ZooKeeper 只運行一臺服務(wù)器上面,這種模式一般用于開發(fā)測試環(huán)境,用于節(jié)省機器數(shù)量,加上開發(fā)調(diào)試不需要特別好的穩(wěn)定性
偽集群模式: 這是一種特殊的集群模式,即一臺服務(wù)器上面部署多個ZooKeeper實例,當然這個時候就需要你這臺服務(wù)器性能比較好。在這種情況下,我們需要通過不同的端口來啟動ZooKeeper實例,以此來通過集群的方式對外提供服務(wù)。
這種模式下,我們只需要修改zoo.cfg下的同一個服務(wù)器不同端口連接地址即可
- server.1=ip1:2888:3888
- server.2=ip1:2889:3889
- server.3=ip1:2890:3890
集群模式: Zookeeper集群 運行在一組機器上,一般三臺以上的機器就可以組成集群了,組成ZooKeeper集群的每一臺機器都會在內(nèi)存中維護當前服務(wù)的狀態(tài),機器之間也會互相保持通信。
只要集群中過半的服務(wù)存活,就能正常對外提供服務(wù),如果說當我們的leader掛掉了,在選舉過程中是無法提供服務(wù)的,直到leader選舉完成!
這種模式下,我們只需要修改zoo.cfg下的不同服務(wù)器的連接地址即可
- server.1=ip1:2888:3888
- server.2=ip2:2888:3888
- server.3=ip3:2888:3888
Zookeeper集群有什么用
ZooKeeper 實現(xiàn)了高性能,高可靠性和有序的訪問。高性能保證了ZooKeeper能應(yīng)用在大型的分布式系統(tǒng)上,高可靠性保證它不會由于單一節(jié)點的故障而造成任何問題。有序的訪問能保證客戶端可以實現(xiàn)較為復(fù)雜的同步操作。
負載均衡
這里說的負載均衡是指軟負載均衡。在分布式環(huán)境中,為了保證高可用性,通常同一個應(yīng)用或同一個服務(wù)的提供方都會部署多份,來達到高可用。
命名服務(wù)
在分布式系統(tǒng)中,通過使用命名服務(wù),客戶端應(yīng)用能夠根據(jù)指定名字來獲取資源或者服務(wù)的地址,提供者等信息。被命名的實體通常可以是集群中的機器,提供的服務(wù)地址、遠程對象等這些我們可以統(tǒng)稱為Name,其中比較常見的就是一些分布式服務(wù)框架中的服務(wù)地址列表。通過調(diào)用ZooKeeper提供創(chuàng)建節(jié)點的API,能夠很容易創(chuàng)建一個全局唯一的Path,這個Path可以作為一個名稱。阿里巴巴集團開源的分布式服務(wù)框架Dubbo中使用ZooKeeper來作為其命名服務(wù),維護全局的服務(wù)地址列表,點擊這里查看Dubbo開源項目。
分布式協(xié)調(diào)
ZooKeeper中特有的Watcher注冊與異步通知機制,能夠?qū)崿F(xiàn)分布式環(huán)境下不同系統(tǒng)之間的通知與協(xié)調(diào),實現(xiàn)對數(shù)據(jù)變更的及時處理,使用方法通常是不同系統(tǒng)都對ZooKeeper同一個Znode進行注冊,監(jiān)聽Znode的變化。如果其中一個系統(tǒng)更新了Znode,那么另外系統(tǒng)也能夠收到通知,并做出相應(yīng)的處理。
集群管理
集群管理主要是包含其中兩點:服務(wù)狀態(tài)監(jiān)聽(退出和加入)、master選舉。
服務(wù)狀態(tài)監(jiān)聽: 所有機器在父目錄下創(chuàng)建臨時目錄節(jié)點,監(jiān)聽父目錄節(jié)點的子節(jié)點變化消息,如果有機器掛掉,這個機器與ZooKeeper的連接斷開,這個創(chuàng)建的臨時目錄節(jié)點就會被刪除,其他機器收到消息,某個服務(wù)下的節(jié)點目錄被刪除,就知道這個某個節(jié)點宕機。
如果有新的機器或者服務(wù)加入,會在該父目錄節(jié)點下創(chuàng)建一個臨時子節(jié)點,所有服務(wù)就會收到通知,有新的目錄產(chǎn)生。
master選舉: master選舉是ZooKeeper中最為經(jīng)典的應(yīng)用場景了,在分布式環(huán)境中,相同的業(yè)務(wù)應(yīng)用分布在不同的機器上,有的業(yè)務(wù)邏輯,通常只需要其中一臺服務(wù)完成,然后其他服務(wù)共享,這樣可以大幅度減少重復(fù)勞動,提高服務(wù)性能,比如 HDFS 中 Active NameNode 的選舉。
通常情況下,我們可以選擇常見的關(guān)系型數(shù)據(jù)庫中的主鍵特性來實現(xiàn),在成為Master的機器都想數(shù)據(jù)庫中插入一條相同主鍵ID的記錄,數(shù)據(jù)庫會幫我們進行主鍵沖突檢查,也就是說,只有一臺機器能夠插入成功,那么我們就認為向數(shù)據(jù)庫中插入數(shù)據(jù)的機器就是Master
但是當我們的Master機器掛掉了,那么誰能夠告訴我們Master掛掉了,關(guān)系型數(shù)據(jù)庫是無法通知我們這個事情的,但是ZooKeeper可以做到。
ZooKeeper能夠保證在分布式高并發(fā)情況下節(jié)點的創(chuàng)建一定能夠保證全局唯一性,ZooKeeper將會保證客戶端無法創(chuàng)建一個已經(jīng)存在的數(shù)據(jù)單元節(jié)點。也就是說,如果同時有多個客戶端請求創(chuàng)建同一個臨時節(jié)點,那么最終一定只有一個客戶端請求能夠創(chuàng)建成功。利用這個特性,就能很容易的在分布式環(huán)境中進行Master選舉了,成功創(chuàng)建該節(jié)點的客戶端所在的機器就成為了Master,同時企業(yè)沒有成功創(chuàng)建該節(jié)點的客戶端,都會在該節(jié)點上注冊一個子節(jié)點變更的Watcher,用于監(jiān)控當前的Master機器是否存活,一旦發(fā)現(xiàn)當前的Master掛了,那么其他客戶端將會重新進行Master選舉,這樣就實現(xiàn)了Master的動態(tài)選舉。
ZooKeeper集群必須是奇數(shù)?
一個ZooKeeper集群通常由一組機器組成,一般是3臺以上就可以組成一個可用的ZooKeeper集群了。只要集群中存在超過一半的機器能夠正常工作,那么ZooKeeper集群就能正常對外提供服務(wù)。
在這里,有一個誤區(qū),就是為了讓 ZooKeeper 群能夠正確的選舉出 leader 我們必須要把 ZooKeeper 集群服務(wù)器的數(shù)量設(shè)置為奇數(shù),其實任意臺的ZooKeeper都可以正常選舉出Leader和運行。
關(guān)于集群服務(wù)數(shù)量中,ZooKeeper官方也給出了奇數(shù)的建議,而且基于ZooKeeper 過半以上存活服務(wù)可用 的特性,如果ZooKeeper需要對外提供服務(wù),那么至少要保證有過半存活的機器能夠正常工作,如果我們想要搭建一臺允許掛點一定數(shù)量(N)的集群機器,那我們至少要部署 2*N+1臺服務(wù)器來搭建ZooKeeper集群。
容錯率
從容錯率來講,我們要保證 過半以上存活的特性
如果我們允許掛掉1臺服務(wù),那我們至少要搭建( 2*1+1)臺服務(wù)器,也是就3臺服務(wù)器(3的半數(shù)為1.5,默認向下取整為1,半數(shù)以上那就是2)
如果我們允許掛掉2臺服務(wù),那我們至少要搭建( 2*1+1)臺服務(wù)器,也是就5臺服務(wù)器(5的半數(shù)為2.5,默認向下取整為2,半數(shù)以上那就是3)
同樣我們部署六臺機器,那么我們遵循過半以上存活服務(wù)可用的特性,同樣也只能掛掉2臺服務(wù)器,因為如果掛掉3臺,無法遵循服務(wù)過半的特性
因此,我們可以從上面條件中看到,對于一個由6臺服務(wù)器構(gòu)成的ZooKeeper集群來說,和一個用5臺服務(wù)器構(gòu)成的ZooKeeper集群,在容災(zāi)能力上沒有任何的顯著優(yōu)勢,所以ZooKeeper集群 通常會設(shè)置成奇數(shù)臺服務(wù)器即可
下載
下載地址:https://zookeeper.apache.org/releases.html
安裝
ZooKeeper安裝首先需要安裝JDK,ZooKeeper的安裝步驟在上一篇文章中介紹過,大家感興趣的可以看一下:Zookeeper入門看這篇就夠了
修改配置
當我們將conf下的 zoo_sample.cfg 文件復(fù)制并重命名為 zoo.cfg 文件后,通過 vim zoo.cfg命令對這個文件進行修改:
- # The number of milliseconds of each tick
- tickTime=2000
- # The number of ticks that the initial
- # synchronization phase can take
- initLimit=10
- # The number of ticks that can pass between
- # sending a request and getting an acknowledgement
- syncLimit=5
- # the directory where the snapshot is stored.
- # do not use /tmp for storage, /tmp here is just
- # example sakes.
- dataDir=/tmp/zookeeper
- # the port at which the clients will connect
- clientPort=2181
- # the maximum number of client connections.
- # increase this if you need to handle more clients
- #maxClientCnxns=60
- #
- # 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
- ## Metrics Providers
- #
- # https://prometheus.io Metrics Exporter
- #metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
- #metricsProvider.httpPort=7000
- #metricsProvider.exportJvmInfo=true
- server.1=192.168.5.129:2888:3888
- server.2=192.168.5.130:2888:3888
- server.3=192.168.5.131:2888:3888
tickTime: 客戶端與服務(wù)端或者服務(wù)端和服務(wù)端之間維持心跳的時間間隔,每隔tickTime時間就會發(fā)送一個心跳,通過心跳不僅能夠用來監(jiān)聽機器的工作狀態(tài),還可以通過心跳來控制follower和Leader的通信時間,默認情況下FL(Follower和Leader)的會話通常是心跳間隔的兩倍,單位為毫秒。
initLimit: 集群中的follower服務(wù)器與Leader服務(wù)器之間的初始連接時能容忍的最多心跳數(shù)量
syncLimit: 急群眾的follower服務(wù)器與leader服務(wù)器之間的請求和回答最多能容忍的心跳數(shù)量
dataDir: 目錄地址,用來存放myid信息和一些版本、日志、服務(wù)器唯一ID等信息
clientPort: 監(jiān)聽客戶端連接的端口
server.n=127.0.0.1:2888:3888
n:代表的是一個數(shù)字,表示這個服務(wù)器的標號 127.0.0.1:IP服務(wù)器地址 2888:ZooKeeper服務(wù)器之間的通信端口 3888:Leader選舉的端口
兩個需要修改的點:
- 修改的是目錄結(jié)構(gòu)(dataDir),不要用它默認的
- 添加server.1 集群服務(wù)器配置信息
官方參考文檔:https://zookeeper.apache.org/doc/r3.5.8/zookeeperStarted.html
創(chuàng)建服務(wù)器ID
在這里我們需要創(chuàng)建一個 myid 的文件,我們需要在 dataDir指定的目錄下,手動創(chuàng)建這個目錄。
創(chuàng)建命令:mkdir-p/tmp/zookeeper
然后在myid 文件里面添加對應(yīng)的server.1中的 “1” 這個數(shù)字,如下所示
- [root@VM-0-7-centos zookeeper]# more myid
- 1
后面的機器,依次在 dataDir指定的目錄下(/tmp/zookeeper),創(chuàng)建 myid 文件,寫上相應(yīng)配置的數(shù)字,比如我們在 zoo.cfg后面寫的是server.1,那么當前myid的文件就寫一個數(shù)字1就可以了
- server.1=192.168.5.129:2888:3888
- server.2=192.168.5.130:2888:3888
- server.3=192.168.5.131:2888:3888
配置環(huán)境變量
為了方便我們可以在全局使用ZooKeeper命令,我們需要配置ZooKeeper的環(huán)境變量。
通過命令:vi/etc/profile
添加ZooKeeper的環(huán)境變量。
- export JAVA_HOME=/usr/local/java/jdk1.8.0_261
- export ZK_HOME=/usr/local/java/apache-zookeeper-3.7.0-bin/
- export PATH=$PATH:$JAVA_HOME/bin:$ZK_HOME/bin
變量生效:source/etc/profile
關(guān)閉防火墻
在這里大家記得,如果是生產(chǎn)或者正式的,需要開放對應(yīng)的端口進行通信。
如果是我們測試用的服務(wù)器,需要關(guān)閉防火墻,不然會有攔截,無法進行服務(wù)之間的通信,在這里我們是測試,關(guān)閉防火墻即可。這里我使用的服務(wù)是CentOS 7.0,默認使用的是firewall作為防火墻。
防火墻設(shè)置
查看防火墻狀態(tài):firewall-cmd--state
立即關(guān)閉防火墻,重啟失效:systemctl stop firewalld.service
禁止開機啟動防火墻:systemctl disable firewalld.service
端口設(shè)置
開放2888端口:firewall-cmd--zone=public--add-port=2888/tcp--permanent
關(guān)閉2888端口:firewall-cmd--zone=public--remove-port=2888/tcp--permanent
啟動服務(wù)
查看日志啟動命令:zkServer.sh start-foreground
后臺啟動命令:zkServer.sh start
停止命令:zkServer.sh stop
查看狀態(tài)命令:zkServer.sh status
我們分別用 zkServer.sh status命令查看節(jié)點狀態(tài),三臺機器中,有兩臺成為了 follower,一臺成為了Leader節(jié)點。
使用命名查看ZooKeeper端口情況:netstat-natp|egrep'(2888|3888)'
端口說明
3888:是選舉用的 2888:是leader接受write請求
因此我們可以看到130這一臺機器出了有 130:2888以外還有130:3888 端口對自身進行監(jiān)聽,這個是保證leader可以進行write操作的命令,具體通信如下所示:
注意事項
如果搭建中出現(xiàn)問題,首先我們需要排查的問題,包含以下幾點
防火墻有沒有關(guān)閉
zoo.cfg 下的文件路徑 dataDir 的目錄有沒有創(chuàng)建,不是自動創(chuàng)建的,需要我們進行手動創(chuàng)建,創(chuàng)建命令 mkdir-p/tmp/zookeeper
我們可以通過 zkServer.sh start-foreground啟動過程的報錯信息
總結(jié)
到這里,關(guān)于ZooKeeper的集群就講解完畢了,主要介紹了ZooKeepe集群的作用和安裝部署,以及原理,今天的ZooKeeper集群到這里就講完了,下期精彩持續(xù)更新中。
碼字不易,感興趣的小伙伴記得點贊關(guān)注~