構建Zookeeper集群(zkcluster) ~一篇文章玩轉zk集群^.^
- 2020 年 12 月 28 日
- 筆記
- Linux Install
概念
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”只需要在集群中的任意一台主機上操作,集群中所有主機都會同步配置資訊。
官方文檔://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 //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