構建Zookeeper叢集(zkcluster) ~一篇文章玩轉zk叢集^.^

Ren發表於2020-12-28

不知道怎麼安裝zk的可以閱讀本部落格文章<安裝Zookeeper到Linux>

概念

Zookeeper叢集是由一個leader(負責人)主機和多個follower(追隨者)或observer(觀察者)主機組成。
構建一個Zookeeper叢集需要有一個leader和一個folloer或observer,共兩臺主機組成,建議最少三臺,當一臺leader故障時,叢集還可以選舉出新的leader,保證叢集正常工作。

leader負責接受寫請求並通知follower/observer同步資料。
所有客戶端的寫請求都會轉發到leader(就算是客戶端連線的是follower/observer),leader會進行原子廣播(atomic broadcast)通知follower/observer從leader的複製資料庫(replicated database)中同步資料,叢集中所有的follower/observer都更新成功或失敗後返回響應給客戶端。
原子廣播:原子性,全部都更新成功或者失敗。

Zk叢集角色說明

leader,領導者,接受所有寫請求,儲存並廣播叢集中的follower/observer同步資料;事務請求的唯一排程者和處理者,保證叢集事務處理的順序性。
follower,追隨者,接受客戶端所有請求,讀請求就自己處理,寫請求就轉發給leader處理;參與事務請求提議的投票(客戶端的一個事務請求,需要半數伺服器投票通過以後才能通知leader提交,以保證叢集中所有主機中資料實時同步);當leader故障時,參與leader選舉投票,有可能成為新的leader。
observer,觀察者,接受客戶端所有請求,讀請求就自己處理。寫請求就轉發給leader處理;不參與投票,不會被選舉為leader。如果一個叢集是由一個leader,一個follower,一個observer組成的話,當leader故障時,叢集則不可用(一個可用叢集需要有兩臺可用伺服器參與投票)。但是當擴充套件了足夠數量的主機節點時,若參與投票節點的數量過多,導致寫入效能下降的時候,則可以考慮將主機節點設定為該型別,可以減少投票參與者數量。

leader的選舉原則

(1)根據zxid選舉leader,zxid越大則約優先,若所有伺服器上的zxid都相同則根據(2)。
(2)根據myid選舉leader,myid越大則越優先。

說明:
zxid:事務ID,伺服器中存放的最新的資料ID,zxid越大說明資料最新。
myid:伺服器ID,在叢集中伺服器的唯一標識。

舉例:
由A,B,C三臺主機組成叢集,三臺主機都是新建的,資料都為空,它們的zxid都是相同的。
A的myid=1,B的myid=2,C的myid=3。
則按順位A,B,C啟動服務,則A和B對比時,B的myid大,則B會被選舉為leader。
在使用過程中,B(leader)故障,又會重新選舉leader,若C的資料最新,zxid大則會被選舉為新的leader,若A,C資料都相同,即zxid相同,則C會被選舉為新的leader,因為它myid最大。

動態重新配置

在3.5.0版本釋出之前,Zookeeper 的成員身份和所有其他配置引數都是靜態的,在啟動期間載入,在執行時是不可變。運維人員使用"滾動重啟"方法來擴充套件或減少叢集中主機節點的數量,這是一種手動密集型且容易出錯的方法來更改導致資料丟失和生產不一致的配置(如果不停止Zk叢集擴充套件或減少主機節點,則可能會出現無法恢復的異常問題)。
從3.5.0版本開始,Zookeeper完全支援自動配置的更改,Zookeeper支援動態的修改配置資訊(增加或減少主機節點),無需服務中斷,同時保持資料一致性。
重新配置"reconfig"只需要在叢集中的任意一臺主機上操作,叢集中所有主機都會同步配置資訊。
官方文件:https://zookeeper.apache.org/doc/r3.5.4-beta/zookeeperReconfig.html
在3.5.0~3版本,任意客戶端都可以動態的使用"reconfig"來修改叢集的配置資訊,這可能會有伺服器被攻破的惡意客戶端隨意的篡改配置資訊,所以在3.5.3之後的版本Zookeeper引入了許可權驗證機制,要使用"reconfig"重新配置功能則客戶端需要先使用"addauth"進行身份驗證。


構建zk叢集

Zk叢集的構建非常簡單,本次只是為了實驗,所以我將在一臺主機上建立不同的Zk程式構建成叢集,若是在生產環境下,建議在不同的主機上執行Zk程式。
注:角色有participant和observer,這邊將主機標記為participant即表示伺服器為參與者,可通過選舉投票成為leader或follower。

程式名稱 myid 主機地址 客戶端埠 API埠 叢集通訊埠 叢集選舉埠 角色
zk01 1 127.0.0.1 1888 1889 2181 8081 participant
zk02 2 127.0.0.1 2888 2889 2182 8082 participant
zk03 3 127.0.0.1 3888 3889 2183 8083 participant

1、安裝JDK

Zookeeper需要JDK的支援。
注:需要先去JDK官網下載安裝包。

root@ubuntu:~# mkdir /usr/local/jdk  # 建立程式安裝目錄
root@ubuntu:~# tar -xvzf jdk-8u211-linux-x64.tar.gz -C /usr/local/jdk/  # 解壓安裝包
root@ubuntu:~# vim /etc/profile  # 配置環境變數
# jdk
export JAVA_HOME="/usr/local/jdk/jdk1.8.0_211/"
export PATH="$JAVA_HOME/bin:$PATH"
root@ubuntu:~# source /etc/profile  # 使系統環境變數立即生效
root@ubuntu:~# java -version  # 檢視java版本以驗證jdk安裝成功
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

2、建立叢集程式目錄

root@ubuntu:~# mkdir /opt/zk-cluster
root@ubuntu:~# mkdir -p /opt/zk-cluster/zk01
root@ubuntu:~# mkdir -p /opt/zk-cluster/zk02
root@ubuntu:~# mkdir -p /opt/zk-cluster/zk03

3、下載二進位制包並解壓

root@ubuntu:~# wget http://mirror.bit.edu.cn/apache/zookeeper/stable/apache-zookeeper-3.5.8-bin.tar.gz
root@ubuntu:~# tar xzvf apache-zookeeper-3.5.8-bin.tar.gz -C /opt/zk-cluster/zk01/
root@ubuntu:~# tar xzvf apache-zookeeper-3.5.8-bin.tar.gz -C /opt/zk-cluster/zk02/
root@ubuntu:~# tar xzvf apache-zookeeper-3.5.8-bin.tar.gz -C /opt/zk-cluster/zk03/

4、建立資料目錄和myid檔案

root@ubuntu:~# mkdir /opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/data
root@ubuntu:~# mkdir /opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/data
root@ubuntu:~# mkdir /opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/data
root@ubuntu:~# echo 1 > /opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/data/myid
root@ubuntu:~# echo 2 > /opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/data/myid
root@ubuntu:~# echo 3 > /opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/data/myid

5、配置Zk

root@ubuntu:~# vim /opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/conf/zoo.cfg  # zk01-主配置
tickTime=2000
# 心跳超時時間,單位為毫秒。客戶端與服務端,服務端與服務端之間的通訊超時時間。
initLimit=10
# 叢集初始化時,follower伺服器和leader伺服器之間超時連線次數(tickTime超時多次)。
syncLimit=5 
# 叢集同步資料時,follower伺服器和leader伺服器之間超時連線次數(tickTime超時多次)。
dataDir=/opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/data
# 資料儲存目錄。
# clientPort=2181
# 客戶端連線所使用的埠。支援舊版本使用的配置,建議在獨立的動態配置檔案的主機節點配置條目中繫結客戶端
# 地址和埠。
maxClientCnxns=100
# 允許接受的最大客戶端連線數。
admin.serverPort=8081
# API監聽埠。

### zk 叢集 ###
standaloneEnabled=false
# 禁用以獨立的方式啟動Zk。將此項值設定為"false"則表示以叢集分散式模式(Distributed)啟用Zk。要禁用此項
# 的前提需要叢集節點主機數量是大於>2。
# 預設情況下,standaloneEnabled=true,如果一開始就有多個伺服器,則它將不允許縮減到包含少於兩個參與者
# (participant)。
reconfigEnabled=true
# 啟用重新配置功能,允許使用"reconfig"指令動態配置叢集,動態的增加和減少主機節點,啟用此功能後,配置將
# 由Zk叢集託管,配置會發生重寫,叢集的配置會獨立到一個單獨的動態檔案中,由配置項"dynamicConfigFile"關
# 聯。使用"reconfig"指令需要啟用許可權驗證功能"-
# Dzookeeper.DigestAuthenticationProvider.superDigest=su:gACzJ4L2A0F2ygTno5HQnfabuik="。
# 注:此功能在3.5.3版本後加入的新功能,如果是之前的版本則不支援。
dynamicConfigFile=/opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic
# 關聯動態配置檔案,獨立的叢集主機節點配置檔案。
root@ubuntu:~# vim /opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic # zk01-動態配置
# 配置格式:
# server.myid=主機地址:叢集通訊埠:叢集選舉埠:角色{參與者(participant)或觀察者(observer)};客
# 戶端監聽地址:監聽埠。
server.1=127.0.0.1:1888:1889:participant;2181
server.2=127.0.0.1:2888:2889:participant;2182
server.3=127.0.0.1:3888:3889:participant;2183
-------------------------------------------------------------------------------------------------------
root@ubuntu:~# vim /opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/conf/zoo.cfg # zk02-主配置
tickTime=2000
initLimit=10
syncLimit=5 
dataDir=/opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/data
maxClientCnxns=100
admin.serverPort=8082
standaloneEnabled=false
reconfigEnabled=true
dynamicConfigFile=/opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic
root@ubuntu:~# vim /opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic # zk02-動態配置
server.1=127.0.0.1:1888:1889:participant;2181
server.2=127.0.0.1:2888:2889:participant;2182
server.3=127.0.0.1:3888:3889:participant;2183
-------------------------------------------------------------------------------------------------------
root@ubuntu:~# vim /opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/conf/zoo.cfg # zk03-主配置
tickTime=2000
initLimit=10
syncLimit=5 
dataDir=/opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/data
maxClientCnxns=100
admin.serverPort=8083
standaloneEnabled=false
reconfigEnabled=true
dynamicConfigFile=/opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic
root@ubuntu:~# vim /opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic # zk03-動態配置
server.1=127.0.0.1:1888:1889:participant;2181
server.2=127.0.0.1:2888:2889:participant;2182
server.3=127.0.0.1:3888:3889:participant;2183

6、配置快捷命令

將叢集中的服務配置成快捷指令,這就會操作更便捷。

root@ubuntu:~# vim /etc/profile.d/alias_zk_cluster.sh
alias zkclient='/opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/bin/zkCli.sh'
alias zkserver01='/opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/bin/zkServer.sh'
alias zkserver02='/opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/bin/zkServer.sh'
alias zkserver03='/opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/bin/zkServer.sh'
root@ubuntu:~# source /etc/profile

7、開啟四字指令和超級管理員許可權認證功能

Zk採用外掛的方式控制一些特殊功能的啟用,所以只需要在啟動的命令中新增以下引數即可。

"-Dzookeeper.4lw.commands.whitelist=*"表示啟用所有四字指令。
"-Dzookeeper.DigestAuthenticationProvider.superDigest=zk:MsjFltVWzlTGMoDYclrWdyEQ9KU="表示設定超級管理員的賬號密碼,使用動態配置功能需要擁有超級管理員的許可權。
root@ubuntu:~# echo -n zk:123|openssl dgst -binary -sha1 |openssl base64  # 基於使用者名稱和密碼組合生成密文密碼(sha1加密+base64編碼後的密碼)
MsjFltVWzlTGMoDYclrWdyEQ9KU=
root@ubuntu:~# vim /opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/bin/zkServer.sh
start)
# 省略...
    nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
    "-Dzookeeper.4lw.commands.whitelist=*" "-Dzookeeper.DigestAuthenticationProvider.superDigest=zk:MsjFltVWzlTGMoDYclrWdyEQ9KU=" \
    "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
    -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
root@ubuntu:~# vim /opt/zk-cluster/zk02/apache-zookeeper-3.5.8-bin/bin/zkServer.sh
# 同上
root@ubuntu:~# vim /opt/zk-cluster/zk03/apache-zookeeper-3.5.8-bin/bin/zkServer.sh
# 同上

8、啟動Zk叢集

root@ubuntu:~# zkserver01 start
root@ubuntu:~# zkserver02 start
root@ubuntu:~# zkserver03 start

9、檢視執行狀態

root@ubuntu:~# zkserver01 status
Mode: follower
root@ubuntu:~# echo conf | nc 127.0.0.1 2181  # 使用四字指令
root@ubuntu:~# echo stat| nc 127.0.0.1 2181
root@ubuntu:~# zkserver02 status
Mode: leader
root@ubuntu:~# echo conf | nc 127.0.0.1 2181  # 使用四字指令
root@ubuntu:~# echo stat| nc 127.0.0.1 2181
root@ubuntu:~# zkserver03 status
Mode: follower
root@ubuntu:~# echo stat| nc 127.0.0.1 2181  # 使用四字指令
root@ubuntu:~# echo conf | nc 127.0.0.1 2181

10、測試叢集同步

在Zk01上建立/test,在zk02、zk03上檢視。
root@ubuntu:~# zkclient -server 127.0.0.1:2181 create /test 'hello world'
Created /test
root@ubuntu:~# zkclient -server 127.0.0.1:2182 get /test
hello world
root@ubuntu:~# zkclient -server 127.0.0.1:2183 get /test
hello world


動態擴充套件Zk主機節點

Zookeeper3.5.0版本以後支援動態的擴充套件和減少主機節點(動態配置功能),新的主機節點加入到叢集中,無需整個叢集停止。
我這邊在之前構建的Zk叢集的基礎上擴充套件一個主機節點zk04。

1、建立程式安裝目錄

root@ubuntu:~# mkdir -p /opt/zk-cluster/zk04 # 建立程式工作目錄

2、解壓安裝包

root@ubuntu:~# tar xzvf apache-zookeeper-3.5.8-bin.tar.gz -C /opt/zk-cluster/zk04 # 解壓安裝包

3、建立資料目錄和myid檔案

root@ubuntu:~# mkdir /opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/data  # 建立資料目錄
root@ubuntu:~# echo 4 > /opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/data/myid  # 建立myid檔案

4、配置新主機節點

root@ubuntu:~# vim /opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/conf/zoo.cfg  # zk04主配置
tickTime=2000
initLimit=10
syncLimit=5 
dataDir=/opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/data
maxClientCnxns=100
admin.serverPort=8084
standaloneEnabled=false
reconfigEnabled=true
dynamicConfigFile=/opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic
root@ubuntu:~# vim /opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/conf/zoo.cfg.dynamic # zk04動態配置
server.1=127.0.0.1:1888:1889:participant;2181
server.2=127.0.0.1:2888:2889:participant;2182
server.3=127.0.0.1:3888:3889:participant;2183
# 新增以下配置只是為了成功啟動服務,當服務加入到叢集中,動態配置會自動同步,與叢集中其他節點配置資訊保
# 持一致。
server.4=127.0.0.1:4888:4889:participant;2184

5、開啟四字指令和超級管理員許可權認證功能

Zk採用外掛的方式控制一些特殊功能的啟用,所以只需要在啟動的命令中新增以下引數即可。

"-Dzookeeper.4lw.commands.whitelist=*"表示啟用所有四字指令。
"-Dzookeeper.DigestAuthenticationProvider.superDigest=zk:MsjFltVWzlTGMoDYclrWdyEQ9KU="表示設定超級管理員的賬號密碼,使用動態配置功能需要擁有超級管理員的許可權。
root@ubuntu:~# echo -n zk:123|openssl dgst -binary -sha1 |openssl base64  # 基於使用者名稱和密碼組合生成密文密碼(sha1加密+base64編碼後的密碼)
MsjFltVWzlTGMoDYclrWdyEQ9KU=
root@ubuntu:~# vim /opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/bin/zkServer.sh  # 開啟四字指令和動態配置功能
start)
# 省略...
    nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
    "-Dzookeeper.4lw.commands.whitelist=*" "-Dzookeeper.DigestAuthenticationProvider.superDigest=zk:MsjFltVWzlTGMoDYclrWdyEQ9KU=" \
    "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
    -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

6、新增快捷命令

root@ubuntu:~# vim /etc/profile.d/alias_zk_cluster.sh  # 新增快捷命令
alias zkclient='/opt/zk-cluster/zk01/apache-zookeeper-3.5.8-bin/bin/zkCli.sh'
# 省略...
alias zkserver04='/opt/zk-cluster/zk04/apache-zookeeper-3.5.8-bin/bin/zkServer.sh'

7、啟動新的Zk服務

root@ubuntu:~# zkserver04 start # 啟動服務

8、檢視執行狀態和配置資訊

通過四字指令"stat"檢視執行狀態,看到新節點的執行模式為"follower",說明新主機節點已經成功加入叢集。
通過四字指令"conf"檢視配置資訊,發現配置已自動同步叢集配置,與叢集中其他主機節點配置資訊保持一致性。

root@ubuntu:~# echo stat | nc 127.0.0.1 2184
Mode: follower
root@ubuntu:~# echo conf | nc 127.0.0.1 2184
# 省略...
membership: 
server.1=127.0.0.1:1888:1889:participant;0.0.0.0:2181
server.2=127.0.0.1:2888:2889:participant;0.0.0.0:2182
server.3=127.0.0.1:3888:3889:participant;0.0.0.0:2183
version=100000000

9、動態新增新主機節點

只需要使用客戶端連線叢集中任意主機節點,動態新增新的主機節點即可,所有主機節點中的配置資訊會自動同步。

root@ubuntu:~# zkclient -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 0] addauth digest zk:123  # 使用超級管理員登入Zk
[zk: 127.0.0.1:2181(CONNECTED) 1] reconfig -add server.4=127.0.0.1:4888:4889:participant;2184  # 新增新的主機節點
[zk: 127.0.0.1:2181(CONNECTED) 2] config  # 檢視當前主機節點配置資訊
server.1=127.0.0.1:1888:1889:participant;0.0.0.0:2181
server.2=127.0.0.1:2888:2889:participant;0.0.0.0:2182
server.3=127.0.0.1:3888:3889:participant;0.0.0.0:2183
server.4=127.0.0.1:4888:4889:participant;0.0.0.0:2184
version=200000002
[zk: 127.0.0.1:2181(CONNECTED) 3] quit

10、檢視配置同步情況

依次檢視叢集中各個主機節點配置資訊,檢視是否一致。
若都一致則說明新的主機節點已成功加入到叢集中!

root@ubuntu:~# echo conf | nc 127.0.0.1 2181
# 省略...
membership: 
server.1=127.0.0.1:1888:1889:participant;0.0.0.0:2181
server.2=127.0.0.1:2888:2889:participant;0.0.0.0:2182
server.3=127.0.0.1:3888:3889:participant;0.0.0.0:2183
server.4=127.0.0.1:4888:4889:participant;0.0.0.0:2184
version=200000002
root@ubuntu:~# echo conf | nc 127.0.0.1 2182
# 同上
root@ubuntu:~# echo conf | nc 127.0.0.1 2183
# 同上
root@ubuntu:~# echo conf | nc 127.0.0.1 2184
# 同上

動態減少Zk主機節點

Zookeeper3.5.0版本以後支援動態的擴充套件和減少主機節點(動態配置功能),減少叢集中的主機節點,只需要從叢集的配置中移除該節點即可,操作非常簡單。
執行移除操作需要超級管理員操作,超級管理員賬號密碼是"zk:123",超級管理員使用者名稱和密碼設定請檢視"構建Zk叢集"。

1、動態移除主機節點

使用客戶端連線任意主機節點,重新配置叢集,移除主機節點即可。

root@ubuntu:~# zkclient -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 1] config  # 檢視叢集配置
server.1=127.0.0.1:1888:1889:participant;0.0.0.0:2181
server.2=127.0.0.1:2888:2889:participant;0.0.0.0:2182
server.3=127.0.0.1:3888:3889:participant;0.0.0.0:2183
server.4=127.0.0.1:4888:4889:participant;0.0.0.0:2184
version=200000002
[zk: 127.0.0.1:2181(CONNECTED) 2] addauth digest zk:123  # 使用超級管理員身份登入Zk
[zk: 127.0.0.1:2181(CONNECTED) 4] reconfig -remove 4  # 移除myid=4的主機節點
Committed new configuration:
server.1=127.0.0.1:1888:1889:participant;0.0.0.0:2181
server.2=127.0.0.1:2888:2889:participant;0.0.0.0:2182
server.3=127.0.0.1:3888:3889:participant;0.0.0.0:2183
version=200000006
[zk: 127.0.0.1:2181(CONNECTED) 5] quit

2、停止已移除的主機節點

root@ubuntu:~# zkserver04 stop

相關文章