亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Zookeeper 集群模式

1. 前言

在我們的生產環境中,Zookeeper 的單機模式無法保證 Zookeeper 服務的高可用性,也就是我們常說的單點故障問題,性能也存在瓶頸。所以在生產環境中,Zookeeper 最好的使用方式就是 Zookeeper 的集群模式,這樣不僅在性能方面比單機模式更好,服務的高可用性也得到了保障。本節我們就來學 Zookeeper 集群模式的部署,以及在集群模式下的 Zookeeper 服務是如何工作的。

2. Zookeeper 集群模式部署

在上一節中,我們學習了 Zookeeper 的單機模式,我們可以在此基礎上進行 Zookeeper 集群模式的部署。Zookeeper 集群的數量通常是大于等于 3 的奇數,比如 3、5、7,但也不宜太多,太多的集群數量會影響集群之間的同步性能。這里我們以 3 的集群數量來進行講解。

Tips: Zookeeper 集群的數量為什么需要奇數個呢?如果采用偶數,在 Leader 節點選舉投票時,有可能會產生兩個 Leader 節點,兩個 Leader 都不能滿足大多數選票的原則,這時就會出現腦裂問題。

集群模式

2.1 集群環境準備

我們需要提供相同環境的 3 臺虛擬機,Zookeeper 和 JDK 環境都已準備好。

Server IP
Server1 192.168.0.77
Server2 192.168.0.88
Server3 192.168.0.99

Tips: 同學們進行配置的時候使用自己的服務器 IP 地址進行配置。

接下來我們來對這 3 臺虛擬機中的 Zookeeper 進行配置。

2.2 集群的 myid 配置

myid 文件的內容為服務器編號,服務器編號我們可以自定義,只要每臺機器不同即可。
首先我們進入 Zookeeper 的根目錄,在 data 文件夾中新建 myid 文件,添加服務器編號,操作如下:

# 進入 Zookeeper 根目錄
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/

Server1 的 myid 配置為 1 :

# echo 在文件末尾添加內容,若文件不存在,會新建此文件
echo '1' > data/myid

Server2 的 myid 配置為 2:

# echo 在文件末尾添加內容,若文件不存在,會新建此文件
echo '2' > data/myid

Server3 的 myid 配置為 3:

# echo 在文件末尾添加內容,若文件不存在,會新建此文件
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 的服務器,這里的 1 要與該服務器的 myid 文件的內容相同;
  • 192.168.0.77: 該服務器的地址;
  • 2888: 服務之間通信的端口,默認值 2888;
  • 3888: 服務之間選舉的端口,默認值 3888。

到這里我們的配置部分就完成了,接下來我們依次啟動 3 臺機器的 Zookeeper 服務。

2.4 啟動服務

進入 bin 目錄,使用 start 命令啟動 Zookeeper 服務:

cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 啟動命令
./zkServer.sh start

啟動完成控制臺會輸出以下內容:

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 查看服務狀態

完成 3 臺機器的 Zookeeper 服務啟動后,我們使用 status 命令來觀察 Zookeeper 服務的狀態:

./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 表示為集群中的從節點
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 表示為集群中的從節點
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 表示為集群中的主節點
Mode: leader

我們可以觀察到,Server1 和 Server2 的狀態是 follower,也就是從節點,Server3 的狀態是 leader,也就是主節點。這樣我們 Zookeeper 一主多從的集群環境就部署好了。接下來我們使用 Zookeeper 客戶端進行測試。

3. Zookeeper 集群的同步

在 Zookeeper 集群服務中,每個 Follower 節點都可以對外提供服務,那么我們操作其中一個 Follower 節點時,如何確保我們獲取的數據與其它 Follower 節點的數據是一樣的呢?在接下來的測試中,我們來觀察 Follower 節點的數據。
我們首先對其中一個 Server 進行操作,使用 zkCli.sh 連接 Server1 的 Zookeeper 服務,查看 Znode 節點:

# 進入 bin 文件夾
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 連接命令
./zkCli.sh 
# 查看根節點下的子節點
ls /
# 只有默認的 zookeeper 節點
[zookeeper]

此時我們使用 create 命令對 Server1 的節點進行增加操作:

 # 創建根節點的子節點 imooc
 create /imooc
 # 輸出 imooc 創建成功
 Created /imooc

創建成功之后我們再來查看一下 Server1 根節點的子節點:

# 查看根節點下的子節點
ls /
# 根節點下的子節點,新增了 imooc 節點
[imooc, zookeeper]

對 Server1 的 Znode 操作成功之后,接下來我們來查看一下 Server2 和 Server3 的 Zookeeper 節點信息:

# 進入 bin 文件夾
cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/
# 連接命令
./zkCli.sh 
# 查看根節點下的子節點
ls /
# 新增加的 imooc 節點和默認的 zookeeper 節點
[imooc, zookeeper]

我們發現,Server2 和 Server3 的 Zookeeper 服務的根節點也有 Server1 中新增的 imooc 節點,為什么 Server1 增加的節點,另外兩個服務也會出現呢?
這個問題其實就是 Zookeeper 集群的同步機制。當其中一個節點的信息被修改時,首先會修改 Leader 節點,然后再將數據同步到集群中所有的 Follower 節點,這樣就確保了集群中所有節點的數據一致。

4. Zookeeper 集群的啟動流程

Zookeeper 集群啟動時,首先會通過配置文件判斷 Zookeeper 的啟動方式是否為集群模式,如果為集群模式,則通過配置文件進行初始化工作,然后集群的節點進行 Leader 選舉,選舉完畢后, Follower 節點與 Leader 節點進行數據同步,完成同步后就可以啟動 Leader 和 Follower 實例了。
 Zookeeper 集群的啟動流程

4.1 初始化

首先在集群啟動的過程中,每個 Zookeeper 服務的主函數會都通過 zoo.cfg 配置文件來判定這個 Zookeeper 服務是以哪種模式啟動的,然后通過配置文件進行初始化工作。
與單機模式初始化不同的是,集群模式的 Zookeeper 服務在初始化過程中還需要配置服務器列表、Leader 選舉算法、會話超時時間等參數。

4.2 Leader 選舉

在所有 Zookeeper 服務初始化完成后,第一件事情就是創建 Java 類 QuorumCnxManager 來進行 Zookeeper 集群的 Leader 選舉。
在選舉過程中,每個 Zookeeper 服務會使用自身的服務器編號 SID 、最新的事務編號 ZXID 、和當前服務器紀元值 currentEpoch 這三個參數去參加選舉,然后根據 zoo.cfg 的 electionAlg 參數來選擇 Leader 選舉算法,來完成 Leader 的選舉,完成選舉后 Leader 會向其它 Zookeeper 服務發起數據同步的通知。

4.3 Follower 同步

Leader 選舉完畢,其它 Zookeeper 服務的狀態就會變為 Follower ,在 Follower 接收到來自 Leader 的通知后, Follower 會創建一個 LearnerHandler 類的實例來處理與 Leader 的數據同步,在半數以上的 Follower 完成數據同步后,Leader 和 Follower 的實例就可以啟動了。

4.4 Leader 和 Follower 啟動

在 Leader 和 Follower 實例啟動時,創建和啟動會話管理器,初始化 Zookeeper 的請求處理鏈,處理器也會在啟動階段串聯請求處理鏈,然后把 Zookeeper 實例注冊到 JMX 服務中,整個 Zookeeper 集群的啟動才算完成。

5. 總結

本節我們學習了如何部署 Zookeeper 集群,Zookeeper 集群的同步機制,以及 Zookeeper 集群的啟動流程。以下是本節內容的總結:

  1. Zookeeper 集群模式的部署。
  2. Zookeeper 集群模式的同步機制。
  3. Zookeeper 集群模式的啟動流程。