ZooKeeper集群操作及集群Master選舉搭建啟動

ZooKeeper介紹

ZooKeeper 是一個為 分佈式應用 提供的 分佈式 、開源的 協調服務

它公開瞭一組簡單的 原語 ,分佈式應用程序可以根據這些原語來實現用於 同步配置維護 以及 命名 的更高級別的服務。

怎麼理解協調服務呢?比如我們有很多應用程序,他們之間都需要讀寫維護一個 id ,那麼這些 id 怎麼命名呢,程序一多,必然會亂套,ZooKeeper 能協調這些服務,解決命名、配置、同步等問題,而做到這些,隻需要一組簡單的 原語 即可:

create : 在樹中的某個位置創建一個節點

delete : 刪除一個節點

exists : 測試節點是否存在於某個位置

get data : 從節點讀取數據

set data : 往一個節點裡寫入數據

get children : 檢索節點的子節點列表

sync : 等待數據被傳播

從這些 ZooKeeper (以下簡稱ZK)的 API 可以看到,都是圍繞 Node 來操作,下文實操看一下怎麼操作 Node

ZooKeeper特征

  • 簡單

ZooKeeper 允許分佈式進程通過 共享的層級命名空間 相互協調,該命名空間的組織類似於標準文件系統。

命名空間由數據寄存器組成,在 ZooKeeper 稱為 znodes ,它們類似於文件和目錄。

與典型的文件系統不同,它是為 存儲 而設計的,ZooKeeper 數據保存在 內存 中,這意味著ZooKeeper 可以實現 高吞吐量低延遲數

ZooKeeper 很重視 高性能高可用性嚴格有序訪問 :性能高意味著它可以在大型分佈式系統中使用;而他又具備可靠性,這使它不會成為單點故障;嚴格的排序意味著可以在客戶端上實現復雜的同步原語。

  • 可被復制(高可用)

像它協調的分佈式進程一樣,ZooKeeper 本身也可以在稱為集合的一組主機上進行復制。

組成ZooKeeper 服務的服務器都必須彼此瞭解。它們維護內存中的狀態鏡像,以及持久存儲中的事務日志和快照。隻要大多數服務器可用,ZooKeeper 服務將可用。

客戶端連接到單個 ZooKeeper 服務器。客戶端維護一個 TCP連接 ,通過該連接發送請求,獲取響應,獲取監視事件並發送心跳。如果與服務器的 TCP連接 斷開,則客戶端將連接到其他服務器。

  • 有序的

ZooKeeper 用一個反映所有 ZooKeeper 事務順序 的數字標記每個更新。後續操作可以使用該命令來實現更高級別的抽象,例如 同步分佈式鎖

讀取為主 的工作負載中,它特別快。

ZooKeeper 應用程序可在數千臺計算機上運行,並且在讀取比寫入更常見的情況下,其性能最佳,比率約為10:1。

分層命名空間

ZooKeeper提供的名稱空間與標準文件系統的名稱空間非常相似。

名稱是由 斜杠/)分隔的一系列路徑元素。ZooKeeper 命名空間中的每個節點均由路徑標識。

一個 ZK Node 可以存儲 1M 數據,Node分為 持久節點臨時性節點

  • 持久節點

與標準文件系統不同,ZooKeeper 命名空間中的每個節點都可以具有與其關聯的 數據 以及 子節點 。就像擁有一個文件系統一樣,該文件系統也允許文件成為目錄。

ZooKeeper旨在存儲協調數據:狀態信息,配置,位置信息等,因此存儲在每個節點上的數據通常很小,在字節到千字節范圍內。

Znodes 維護一個統計信息結構,其中包括用於 數據更改ACL更改(權限控制)時間戳的版本號 ,以允許進行 緩存驗證協調更新

Znode 的數據每次更改時,版本號都會增加。例如,每當客戶端檢索數據時,它也會接收數據的版本。

原子地讀取和寫入存儲在名稱空間中每個 Znode 上的數據。讀取將獲取與znode關聯的所有數據字節,而寫入將替換所有數據。每個節點都有一個訪問控制列表(ACL),用於限制誰可以做什麼。

  • 臨時節點

隻要創建 Znode 的會話處於 活動狀態 ,這些 Znode 就一致存在。會話結束時,將刪除 Znode ,這就是臨時節點。

類比於web容器比如tomcat的session,創建臨時節點的session存在,則node存在,session結束,刪除node。

以上是理論知識,還是實際操作一遍比較靠譜,理解一下zk創建連接、node、session這些概念,以及看看zk集群的leader出故障後,選出leader的速度。

搭建ZK集群

首先準備 4 臺 CentOS 7 虛擬機,都安裝好瞭JDK 8(JDK版本最好不要小於8)。

這四臺虛擬機主機名稱分別設置為:zknode01zknode02zknode03zknode04

hostnamectl set-hostname zknode01

主機名在配置 ZooKeeper 集群的時候有用。

主機名稱配置好之後,還需要配置主機名和IP地址的映射關系,每臺主機均編輯 /etc/hosts 文件,末尾添加如下內容:

192.168.242.11 zknode01
192.168.242.12 zknode02
192.168.242.13 zknode03
192.168.242.14 zknode04

保證每臺主機都能互相 ping 通:

接下來,先安裝配置好其中一臺服務器的 ZooKeeper ,然後用 scp 分發到各個服務器,再分別修改 zk serverid ,這樣不用每臺虛擬機都執行一遍相同的操作。

下載zk,註意一定要是apache-zookeeper-3.7.1-bin.tar.gz這個帶bin的,否則如果不是帶bin的,啟動的時候會報如下錯誤:

Error: Could not find or load main class org.apache.zookeeper.server.quorum.QuorumPeerMain
Caused by: java.lang.ClassNotFoundException: org.apache.zookeeper.server.quorum.QuorumPeerMain

保姆式安裝zk步驟:

將下載好的 apache-zookeeper-3.7.1-bin.tar.gz 放到/opt目錄下
1. cd /opt
2. tar xf apache-zookeeper-3.7.1-bin.tar.gz
3. mv apache-zookeeper-3.7.1-bin zookeeper
4. vi /etc/profile
export JAVA_HOME=/usr/local/java
export ZK_HOME=/opt/zookeeper
export PATH=$PATH:$JAVA_HOME/bin:$ZK_HOME/bin
5. source /etc/profile
6. cd /opt/zookeeper/conf
7. cp zoo_sample.cfg zoo.cfg
8. vi zoo.cfg
設置 dataDir=/var/zookeeper
末尾添加:
server.1=zknode01:2888:3888
server.2=zknode02:2888:3888
server.3=zknode03:2888:3888
server.4=zknode04:2888:3888
9. mkdir -p /var/zookeeper
10. echo 1 > /var/zookeeper/myid

這樣 zknode01 的 zkserver 就搭建好瞭,現在將 ZooKeeper目錄配置文件 分發到其餘三臺服務器:

# 傳到 zknode02
scp -r /opt/zookeeper/ root@zknode02:/opt/
scp /etc/profile root@zknode02:/etc
# 傳到 zknode03
scp -r /opt/zookeeper/ root@zknode03:/opt/
scp /etc/profile root@zknode03:/etc
# 傳到 zknode04
scp -r /opt/zookeeper/ root@zknode04:/opt/
scp /etc/profile root@zknode04:/etc

別忘瞭 ,每臺主機都需要執行 source /etc/profile 和創建 /var/zookeeper/myid 文件,myid 的內容分別為 2,3,4 。

這樣 zk集群 就搭建好瞭。

啟動zk集群

按順序啟動 zknode01zknode02zknode03zknode04 的zk服務:

zkServer.sh start-foreground

zk默認後臺啟動,start-foreground表示前臺啟動,方便看日志。

啟動zknode01的zk server:

會報錯,因為 zoo.cfg 配置瞭4臺主機,其餘三臺還未啟動,接著啟動 zknode02 的:

現象同 zknode01 ,繼續啟動第三臺:

這個時候也會報 zknode04 連接不上(因為還沒啟動),但是整個zk集群已經啟動瞭,並且選擇瞭 zknode03 這個為leader。

zknode04 也啟動一下:

啟動完成後,開一個 zknode01 的zk客戶端:

zkCli.sh
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
	addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
	addauth scheme auth
	close 
	config [-c] [-w] [-s]
	connect host:port
	create [-s] [-e] [-c] [-t ttl] path [data] [acl]
	delete [-v version] path
	deleteall path [-b batch size]
	delquota [-n|-b] path
	get [-s] [-w] path
	getAcl [-s] path
	getAllChildrenNumber path
	getEphemerals path
	history 
	listquota path
	ls [-s] [-w] [-R] path
	printwatches on|off
	quit 

用上面的命令操作一波:

[zk: localhost:2181(CONNECTED) 1] ls
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 3] 
[zk: localhost:2181(CONNECTED) 3] create /laogong
Created /laogong
[zk: localhost:2181(CONNECTED) 4] ls /
[laogong, zookeeper]
[zk: localhost:2181(CONNECTED) 5] get /laogong 
null
[zk: localhost:2181(CONNECTED) 6] create /laogong "laogong"
Node already exists: /laogong
[zk: localhost:2181(CONNECTED) 7] delete /laogong
[zk: localhost:2181(CONNECTED) 8] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 9] create /laogong "laogong"
Created /laogong
[zk: localhost:2181(CONNECTED) 10] ls /
[laogong, zookeeper]
[zk: localhost:2181(CONNECTED) 11] get /laogong
laogong
[zk: localhost:2181(CONNECTED) 12] create /laogong/laopo "laopo"
Created /laogong/laopo
[zk: localhost:2181(CONNECTED) 13] ls /
[laogong, zookeeper]
[zk: localhost:2181(CONNECTED) 14] ls /laogong
[laopo]
[zk: localhost:2181(CONNECTED) 15] get /laogong/laopo
laopo
[zk: localhost:2181(CONNECTED) 16] 

上面的操作我都是在 zknode01 上面連接zk進行操作的,來看一下,在其他zkserver上有沒有同步過來數據:

發現數據已經同步,zknode03zknode04 數據也同步瞭。

再來看一下連接 zknode02 的連接狀態:

[root@zknode02 ~]# netstat -natp   |   egrep  '(2888|3888)' 
tcp6       0      0 192.168.242.12:3888     :::*                    LISTEN      9530/java           
tcp6       0      0 192.168.242.12:3888     192.168.242.13:47474    ESTABLISHED 9530/java           
tcp6       0      0 192.168.242.12:37804    192.168.242.13:2888     ESTABLISHED 9530/java           
tcp6       0      0 192.168.242.12:3888     192.168.242.14:47530    ESTABLISHED 9530/java           
tcp6       0      0 192.168.242.12:39666    192.168.242.11:3888     ESTABLISHED 9530/java

連接狀態分析:

上圖是從 zknode02 服務器查看的,通過查看每臺服務器,最終,zk集群的服務器每臺都 互相通信

這個 3888 端口就是選舉master用的,而 2888 端口是leader接受write請求用的。

zk集群master選舉

前面演示瞭有 4 個服務器的 zk集群 ,其中 zknode03 是 leader 。

現在我把 zknode03 服務幹掉:

^C[root@zknode03 conf]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Error contacting service. It is probably not running.
[root@zknode03 conf]# 
[root@localhost ~]# 

再來分別看一下 zknode01 ~ zknode04的 zk server 狀態:

可以看到 zknode04 自動成瞭 leader !

事實上,zk集群 選舉 leader 采用的是 謙讓 的辦法,誰的 id 大,選舉誰。

那麼前面為什麼zknode3是leader呢?

因為我啟動的順序是 zknode01 ~ zknode04 啟動的,當 zknode03 的zk server 啟動的時候,已經 滿足集群的最少節點數 瞭,而且 zknode03 的 id 是 當時 最大的,所以 zknode03 的 server自動成瞭 leader 。

以上就是ZooKeeper集群操作及集群Master選舉搭建啟動的詳細內容,更多關於ZooKeeper集群操作選舉的資料請關註WalkonNet其它相關文章!

推薦閱讀: