Zookeeper 集群模式
1. 前言
在我們的生產(chǎn)環(huán)境中,Zookeeper 的單機模式無法保證 Zookeeper 服務(wù)的高可用性,也就是我們常說的單點故障問題,性能也存在瓶頸。所以在生產(chǎn)環(huán)境中,Zookeeper 最好的使用方式就是 Zookeeper 的集群模式,這樣不僅在性能方面比單機模式更好,服務(wù)的高可用性也得到了保障。本節(jié)我們就來學(xué) Zookeeper 集群模式的部署,以及在集群模式下的 Zookeeper 服務(wù)是如何工作的。
2. Zookeeper 集群模式部署
在上一節(jié)中,我們學(xué)習(xí)了 Zookeeper 的單機模式,我們可以在此基礎(chǔ)上進行 Zookeeper 集群模式的部署。Zookeeper 集群的數(shù)量通常是大于等于 3 的奇數(shù),比如 3、5、7,但也不宜太多,太多的集群數(shù)量會影響集群之間的同步性能。這里我們以 3 的集群數(shù)量來進行講解。
Tips: Zookeeper 集群的數(shù)量為什么需要奇數(shù)個呢?如果采用偶數(shù),在 Leader 節(jié)點選舉投票時,有可能會產(chǎn)生兩個 Leader 節(jié)點,兩個 Leader 都不能滿足大多數(shù)選票的原則,這時就會出現(xiàn)腦裂問題。
2.1 集群環(huán)境準備
我們需要提供相同環(huán)境的 3 臺虛擬機,Zookeeper 和 JDK 環(huán)境都已準備好。
Server | IP |
---|---|
Server1 | 192.168.0.77 |
Server2 | 192.168.0.88 |
Server3 | 192.168.0.99 |
Tips: 同學(xué)們進行配置的時候使用自己的服務(wù)器 IP 地址進行配置。
接下來我們來對這 3 臺虛擬機中的 Zookeeper 進行配置。
2.2 集群的 myid 配置
myid 文件的內(nèi)容為服務(wù)器編號,服務(wù)器編號我們可以自定義,只要每臺機器不同即可。
首先我們進入 Zookeeper 的根目錄,在 data 文件夾中新建 myid 文件,添加服務(wù)器編號,操作如下:
# 進入 Zookeeper 根目錄
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/
Server1 的 myid 配置為 1 :
# echo 在文件末尾添加內(nèi)容,若文件不存在,會新建此文件
echo '1' > data/myid
Server2 的 myid 配置為 2:
# echo 在文件末尾添加內(nèi)容,若文件不存在,會新建此文件
echo '2' > data/myid
Server3 的 myid 配置為 3:
# echo 在文件末尾添加內(nèi)容,若文件不存在,會新建此文件
echo '3' > data/myid
配置好了 myid,接下來我們對 zoo.cfg 進行配置。
2.3 集群的 cfg 配置
我們進入 Zookeeper 根目錄中的 conf 文件夾,編輯 zoo.cfg 文件:
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/conf/
vi zoo.cfg
在 zoo.cfg 配置文件的末尾添加以下配置,這里每臺機器都是同樣的配置。
server.1=192.168.0.77:2888:3888
server.2=192.168.0.88:2888:3888
server.3=192.168.0.99:2888:3888
我們來介紹一下這一段配置的含義,以 server.1=192.168.0.77:2888:3888
為例:
- server.1: 表示編號為 1 的服務(wù)器,這里的 1 要與該服務(wù)器的 myid 文件的內(nèi)容相同;
- 192.168.0.77: 該服務(wù)器的地址;
- 2888: 服務(wù)之間通信的端口,默認值 2888;
- 3888: 服務(wù)之間選舉的端口,默認值 3888。
到這里我們的配置部分就完成了,接下來我們依次啟動 3 臺機器的 Zookeeper 服務(wù)。
2.4 啟動服務(wù)
進入 bin 目錄,使用 start 命令啟動 Zookeeper 服務(wù):
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 啟動命令
./zkServer.sh start
啟動完成控制臺會輸出以下內(nèi)容:
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
2.5 查看服務(wù)狀態(tài)
完成 3 臺機器的 Zookeeper 服務(wù)啟動后,我們使用 status 命令來觀察 Zookeeper 服務(wù)的狀態(tài):
./zkServer.sh status
Server1:
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
# follower 表示為集群中的從節(jié)點
Mode: follower
Server2:
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
# follower 表示為集群中的從節(jié)點
Mode: follower
Server3:
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
# leader 表示為集群中的主節(jié)點
Mode: leader
我們可以觀察到,Server1 和 Server2 的狀態(tài)是 follower,也就是從節(jié)點,Server3 的狀態(tài)是 leader,也就是主節(jié)點。這樣我們 Zookeeper 一主多從的集群環(huán)境就部署好了。接下來我們使用 Zookeeper 客戶端進行測試。
3. Zookeeper 集群的同步
在 Zookeeper 集群服務(wù)中,每個 Follower 節(jié)點都可以對外提供服務(wù),那么我們操作其中一個 Follower 節(jié)點時,如何確保我們獲取的數(shù)據(jù)與其它 Follower 節(jié)點的數(shù)據(jù)是一樣的呢?在接下來的測試中,我們來觀察 Follower 節(jié)點的數(shù)據(jù)。
我們首先對其中一個 Server 進行操作,使用 zkCli.sh 連接 Server1 的 Zookeeper 服務(wù),查看 Znode 節(jié)點:
# 進入 bin 文件夾
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 連接命令
./zkCli.sh
# 查看根節(jié)點下的子節(jié)點
ls /
# 只有默認的 zookeeper 節(jié)點
[zookeeper]
此時我們使用 create 命令對 Server1 的節(jié)點進行增加操作:
# 創(chuàng)建根節(jié)點的子節(jié)點 imooc
create /imooc
# 輸出 imooc 創(chuàng)建成功
Created /imooc
創(chuàng)建成功之后我們再來查看一下 Server1 根節(jié)點的子節(jié)點:
# 查看根節(jié)點下的子節(jié)點
ls /
# 根節(jié)點下的子節(jié)點,新增了 imooc 節(jié)點
[imooc, zookeeper]
對 Server1 的 Znode 操作成功之后,接下來我們來查看一下 Server2 和 Server3 的 Zookeeper 節(jié)點信息:
# 進入 bin 文件夾
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 連接命令
./zkCli.sh
# 查看根節(jié)點下的子節(jié)點
ls /
# 新增加的 imooc 節(jié)點和默認的 zookeeper 節(jié)點
[imooc, zookeeper]
我們發(fā)現(xiàn),Server2 和 Server3 的 Zookeeper 服務(wù)的根節(jié)點也有 Server1 中新增的 imooc 節(jié)點,為什么 Server1 增加的節(jié)點,另外兩個服務(wù)也會出現(xiàn)呢?
這個問題其實就是 Zookeeper 集群的同步機制。當其中一個節(jié)點的信息被修改時,首先會修改 Leader 節(jié)點,然后再將數(shù)據(jù)同步到集群中所有的 Follower 節(jié)點,這樣就確保了集群中所有節(jié)點的數(shù)據(jù)一致。
4. Zookeeper 集群的啟動流程
Zookeeper 集群啟動時,首先會通過配置文件判斷 Zookeeper 的啟動方式是否為集群模式,如果為集群模式,則通過配置文件進行初始化工作,然后集群的節(jié)點進行 Leader 選舉,選舉完畢后, Follower 節(jié)點與 Leader 節(jié)點進行數(shù)據(jù)同步,完成同步后就可以啟動 Leader 和 Follower 實例了。
4.1 初始化
首先在集群啟動的過程中,每個 Zookeeper 服務(wù)的主函數(shù)會都通過 zoo.cfg 配置文件來判定這個 Zookeeper 服務(wù)是以哪種模式啟動的,然后通過配置文件進行初始化工作。
與單機模式初始化不同的是,集群模式的 Zookeeper 服務(wù)在初始化過程中還需要配置服務(wù)器列表、Leader 選舉算法、會話超時時間等參數(shù)。
4.2 Leader 選舉
在所有 Zookeeper 服務(wù)初始化完成后,第一件事情就是創(chuàng)建 Java 類 QuorumCnxManager 來進行 Zookeeper 集群的 Leader 選舉。
在選舉過程中,每個 Zookeeper 服務(wù)會使用自身的服務(wù)器編號 SID 、最新的事務(wù)編號 ZXID 、和當前服務(wù)器紀元值 currentEpoch 這三個參數(shù)去參加選舉,然后根據(jù) zoo.cfg 的 electionAlg 參數(shù)來選擇 Leader 選舉算法,來完成 Leader 的選舉,完成選舉后 Leader 會向其它 Zookeeper 服務(wù)發(fā)起數(shù)據(jù)同步的通知。
4.3 Follower 同步
Leader 選舉完畢,其它 Zookeeper 服務(wù)的狀態(tài)就會變?yōu)?Follower ,在 Follower 接收到來自 Leader 的通知后, Follower 會創(chuàng)建一個 LearnerHandler 類的實例來處理與 Leader 的數(shù)據(jù)同步,在半數(shù)以上的 Follower 完成數(shù)據(jù)同步后,Leader 和 Follower 的實例就可以啟動了。
4.4 Leader 和 Follower 啟動
在 Leader 和 Follower 實例啟動時,創(chuàng)建和啟動會話管理器,初始化 Zookeeper 的請求處理鏈,處理器也會在啟動階段串聯(lián)請求處理鏈,然后把 Zookeeper 實例注冊到 JMX 服務(wù)中,整個 Zookeeper 集群的啟動才算完成。
5. 總結(jié)
本節(jié)我們學(xué)習(xí)了如何部署 Zookeeper 集群,Zookeeper 集群的同步機制,以及 Zookeeper 集群的啟動流程。以下是本節(jié)內(nèi)容的總結(jié):
- Zookeeper 集群模式的部署。
- Zookeeper 集群模式的同步機制。
- Zookeeper 集群模式的啟動流程。