覺得有幫助的,請多多支援部落客,點贊關注哦~
文章目錄
- Zookeeper
-
- 一、Zookeeper概述
-
- 1、概述
- 2、特點
- 3、資料結構
- 4、應用場景
- 5、下載下傳位址
- 二、Zookeeper 安裝
-
- 1、本地模式安裝部署
-
- 1.1、前置準備
- 1.2、安裝配置
- 1.3、啟動Zookeeper
- 2、zoo.cfg 檔案中配置參數解讀
- 三、Zookeeper 内部原理
-
- 1、選舉機制
- 2、節點類型
- 3、stat 結構體
- 4、監聽器原理
-
- 4.1、監聽原理詳解
- 4.2、常見的監聽
- 5、寫資料流程
- 四、Zookeeper分布式安裝部署
-
- 1、叢集規劃
- 2、解壓安裝
- 3、配置 zoo.cfg 檔案
- 4、叢集操作
- 5、啟動zookeeper叢集
- 6、檢視狀态
- 五、用戶端指令行操作
-
- 1、stat擷取指定節點的狀态資訊 status
- 2、Is某節點下的所有子節點
- 3、Is2是Is和stat兩個指令的結合
- 4、create建立節點
- 5、修改節點上的資料内容
- 6、删除節點
- 7、deleteall遞歸删除節點
- 8、Znode節點的ACL權限
- 六、Zookeeper API應用
-
- 1、引入依賴
- 2、代碼測試
Zookeeper
一、Zookeeper概述
1、概述
- Zookeeper 是一個開源的分布式的,為分布式應用提供協調服務的 Apache 項目。
- Zookeeper 從設計模式角度來了解:是一個基于觀察者模式設計的分布式服務管理架構,它負責存儲和管理大家都關心的資料,然後接受觀察者的注冊,一旦這些資料的狀态發生變化,Zookeeper 就将負責通知已經在 Zookeeper 上注冊的那些觀察者做出相應的反應,進而實作叢集中類似 Master/Slave 管理模式
- 主要有:主從模式、監聽模式。
- Zookeeper=檔案系統+通知機制
- Zookeeper維護一個類似檔案系統的資料結構。
2、特點
- Zookeeper:一個上司者(leader),多個跟随者(follower)組成的叢集。
- Leader 負責進行投票的發起和決議,更新系統狀态
- Follower 用于接收客戶請求并向用戶端傳回結果,在選舉 Leader 過程中參與投票
- 叢集中隻要有半數以上節點存活,Zookeeper 叢集就能正常服務。
- 全局資料一緻:每個 server 儲存一份相同的資料副本,client 無論連接配接到哪個 server,資料都是一緻的。
- 更新請求順序進行,來自同一個 client 的更新請求按其發送順序依次執行。
- 資料更新原子性,一次資料更新要麼成功,要麼失敗。
- 實時性,在一定時間範圍内,client 能讀到最新資料。
3、資料結構
ZooKeeper 資料模型的結構與 Unix 檔案系統很類似,整體上可以看作是一棵樹,每個節點稱做一個 ZNode。
很顯然 zookeeper 叢集自身維護了一套資料結構。這個存儲結構是一個樹形結構,其上的每一個節點,我們稱之為"znode",每一個 znode 預設能夠存儲 1MB 的資料,每個 ZNode都可以通過其路徑唯一辨別
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxMGVNJTUq10dRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzYzM4MjM1EjMxEzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
4、應用場景
提供的服務包括:分布式消息同步和協調機制、伺服器節點動态上下線、統一配置管理、負載均衡、叢集管理等。
5、下載下傳位址
官方網站:https://zookeeper.apache.org/
直接下載下傳推薦連結: https://ftp.riken.jp/net/apache/zookeeper/
https://ftp.riken.jp/net/apache/zookeeper/
二、Zookeeper 安裝
1、本地模式安裝部署
1.1、前置準備
安裝JDK,不多說了。。之前的文章有很多遍。
1.2、安裝配置
# 上傳到Linux
[[email protected] model]$ rz
# 解壓到model
[[email protected] model]$ tar -zxvf apache-zookeeper-3.5.7-bin -C ../model
# 重命名
[[email protected] model]$ mv apache-zookeeper-3.5.7-bin/ zookeeper-3.5.7
# 修改配置檔案zoo.cfg(類似mapred-site.xml)
# 1、建立目錄
[[email protected] zookeeper-3.5.7]$ mkdir data
# 2、進入conf
[[email protected] zookeeper-3.5.7]$ cd conf
# 3、複制zoo_sample.cfg
[[email protected] conf]$ cp zoo_sample.cfg zoo.cfg
# 4、修改zoo.cfg
[[email protected] conf]$ vi zoo.cfg
dataDir=/opt/model/zookeeper-3.5.7/data
# 配置環境變量
[[email protected] conf]$ sudo vim /etc/profile
[[email protected] conf]$ source /etc/profile
[[email protected] conf]$ echo $ZOOKEEPER_HOME
/opt/model/zookeeper-3.5.7
1.3、啟動Zookeeper
# 啟動zookeeper
[[email protected] bin]$ zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
# 檢視程序是否啟動
[[email protected] bin]$ jps
2251 QuorumPeerMain
2317 Jps
# 檢視zookeeper狀态
[[email protected] bin]$ zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: standalone
# 啟動用戶端操作
[[email protected] bin]$ zkCli.sh
# 建立node2節點
[zk: localhost:2181(CONNECTED) 0] create /node2
Created /node2
# 檢視/下節點
[zk: localhost:2181(CONNECTED) 1] ls /
[node2, zookeeper]
# 退出用戶端
[zk: localhost:2181(CONNECTED) 2] quit
# 停止zookeeper
[[email protected] bin]$ zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
2、zoo.cfg 檔案中配置參數解讀
-
tickTime:通信心跳數,Zookeeper伺服器心跳時間,機關毫秒
Zookeeper使用的基本時間,伺服器之間或用戶端與伺服器之間維持心跳的時間間隔,也就是每個tickTime時間就會發送一個心跳,時間機關為毫秒。
它用于心跳機制,并且設定最小的session逾時時間為兩倍心跳時間。(session的最小逾時時間是2*tickTime)
-
initLimit:LF初始通信時限
叢集中的follower跟随者伺服器(F)與leader上司者伺服器(L)之間初始連接配接時能容忍的最多心跳數(tickTime的數量),用它來限定叢集中的Zookeeper伺服器連接配接到Leader的時限。
投票選舉新leader的初始化時間
Follower在啟動過程中,會從Leader同步所有最新資料,然後确定自己能夠對外服務的起始狀态。
Leader允許F在initLimit時間内完成這個工作。
-
syncLimit:LF 同步通信時限
叢集中Leader與Follower之間的最大響應時間機關,假如響應超過syncLimit * tickTime,Leader認為Follwer死掉,從伺服器清單中删除Follwer。
在運作過程中,Leader負責與ZK叢集中所有機器進行通信,例如通過一些心跳檢測機制,來檢測機器的存活狀态。
如果L發出心跳包在syncLimit之後,還沒有從F那收到響應,那麼就認為這個F已經不線上了。
-
dataDir:資料檔案目錄+資料持久化路徑
儲存記憶體資料庫快照資訊的位置,如果沒有其他說明,更新的事務日志也儲存到資料庫。
-
clientPort:用戶端連接配接端口
監聽用戶端連接配接的端口
三、Zookeeper 内部原理
1、選舉機制
- 半數機制(Paxos 協定):叢集中半數以上機器存活,叢集可用。是以 zookeeper适合裝在奇數台機器上。
- Zookeeper 雖然在配置檔案中并沒有指定 master 和 slave。但是,zookeeper 工作時,是有一個節點為 leader,其他則為 follower,Leader 是通過内部的選舉機制臨時産生的。
-
以一個簡單的例子來說明整個選舉的過程。
假設有五台伺服器組成的 zookeeper 叢集,它們的 id 從 1-5,同時它們都是最新啟動的,也就是沒有曆史資料,在存放資料量這一點上,都是一樣的。假設這些伺服器依序啟動,來看看會發生什麼。
Zookeeper總結Zookeeper
- 伺服器 1 啟動,此時隻有它一台伺服器啟動了,它發出去的報沒有任何響應,是以它的選舉狀态一直是 LOOKING 狀态。
- 伺服器 2 啟動,它與最開始啟動的伺服器 1 進行通信,互相交換自己的選舉結果,由于兩者都沒有曆史資料,是以 id 值較大的伺服器 2 勝出,但是由于沒有達到超過半數以上的伺服器都同意選舉它(這個例子中的半數以上是 3),是以伺服器 1、2 還是繼續保持LOOKING 狀态。
- 伺服器 3 啟動,根據前面的理論分析,伺服器 3 成為伺服器 1、2、3 中的老大,而與上面不同的是,此時有三台伺服器選舉了它,是以它成為了這次選舉的 leader。
- 伺服器 4 啟動,根據前面的分析,理論上伺服器 4 應該是伺服器 1、2、3、4 中最大的,但是由于前面已經有半數以上的伺服器選舉了伺服器 3,是以它隻能接收當小弟的命了。
- 伺服器 5 啟動,同 4 一樣當小弟。
2、節點類型
1、Znode 有兩種類型:
- 短暫(ephemeral):用戶端和伺服器端斷開連接配接後,建立的節點自己删除
- 持久(persistent):用戶端和伺服器端斷開連接配接後,建立的節點不删除
2、Znode 有四種形式的目錄節點(預設是 persistent )
-
持久化目錄節點(PERSISTENT)
用戶端與 zookeeper 斷開連接配接後,該節點依舊存在
-
持久化順序編号目錄節點(PERSISTENT_SEQUENTIAL)
用戶端與 zookeeper 斷開連接配接後,該節點依舊存在,隻是 Zookeeper 給該節點名稱進行順序編号
-
臨時目錄節點(EPHEMERAL)
用戶端與 zookeeper 斷開連接配接後,該節點被删除
-
臨時順序編号目錄節點(EPHEMERAL_SEQUENTIAL)
用戶端與 zookeeper 斷開連接配接後,該節點被删除,隻是 Zookeeper 給該節點名稱進行順序編号
3、建立 znode 時設定順序辨別,znode 名稱後會附加一個值,順序号是一個單調遞增的計數器,由父節點維護
4、在分布式系統中,順序号可以被用于為所有的事件進行全局排序,這樣用戶端可以通過順序号推斷事件的順序
3、stat 結構體
-
1)czxid- 引起這個 znode 建立的 zxid,建立節點的事務的 zxid每次修改 ZooKeeper 狀态都會收到一個 zxid 形式的時間戳,也就是 ZooKeeper 事務 ID。
事務 ID 是 ZooKeeper 中所有修改總的次序。每個修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那麼 zxid1 在 zxid2 之前發生。
- 2)ctime - znode 被建立的毫秒數(從 1970 年開始)
- 3)mzxid - znode 最後更新的 zxid
- 4)mtime - znode 最後修改的毫秒數(從 1970 年開始)
- 5)pZxid-znode 最後更新的子節點 zxid
- 6)cversion - znode 子節點變化号,znode 子節點修改次數
- 7)dataversion - znode 資料變化号
- 8)aclVersion - znode 通路控制清單的變化号
- 9)ephemeralOwner- 如果是臨時節點,這個是 znode 擁有者的 session id。如果不是臨時節點則是 0。
- 10)dataLength- znode 的資料長度
- 11)numChildren - znode 子節點數量
4、監聽器原理
4.1、監聽原理詳解
- 首先要有一個 main()線程
- 在 main 線程中建立 Zookeeper 用戶端,這時就會建立兩個線程,一個負責網絡連接配接通信(connet),一個負責監聽(listener)。
- 通過 connect 線程将注冊的監聽事件發送給 Zookeeper。
- 在 Zookeeper 的注冊監聽器清單中将注冊的監聽事件添加到清單中。
- Zookeeper 監聽到有資料或路徑變化,就會将這個消息發送給 listener 線程。
- listener 線程内部調用了 process()方法。
4.2、常見的監聽
- 監聽節點資料的變化:get path [watch](過時);get -s -w path(推薦)
- 監聽子節點增減的變化:ls path [watch](過時);ls -w path(推薦)
5、寫資料流程
ZooKeeper 的寫資料流程主要分為以下幾步:
- 比如 Client 向 ZooKeeper 的 Server1 上寫資料,發送一個寫請求。
- 如果 Server1 不是 Leader,那麼 Server1 會把接受到的請求進一步轉發給 Leader,因為每個 ZooKeeper 的 Server 裡面有一個是 Leader。這個 Leader 會将寫請求廣播給各個Server,比如 Server1 和 Server2, 各個 Server 寫成功後就會通知 Leader。
- 當 Leader 收到大多數 Server 資料寫成功了,那麼就說明資料寫成功了。如果這裡三個節點的話,隻要有兩個節點資料寫成功了,那麼就認為資料寫成功了。寫成功之後,Leader 會告訴 Server1 資料寫成功了。
- Server1 會進一步通知 Client 資料寫成功了,這時就認為整個寫操作成功。ZooKeeper整個寫資料流程就是這樣的。
四、Zookeeper分布式安裝部署
1、叢集規劃
在 biubiubiu01、biubiubiu02和 biubiubiu03三個節點上部署 Zookeeper。
首先隻在biubiubiu01上部署,完畢後,分發到biubiubiu02、biubiubiu03。
2、解壓安裝
# 操作biubiubiu01
# 上傳zookeeper檔案
[[email protected] software]$ rz
# 解壓到model下
[[email protected] software]$ tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C ../model
# 重命名
[[email protected] model]$ mv apache-zookeeper-3.5.7-bin.tar.gz zookeeper-3.5.7
# 建立檔案夾data
[[email protected] zookeeper-3.5.7]$ mkdir data
3、配置 zoo.cfg 檔案
# 複制/opt/model/zookeeper-3.5.7/conf 這個目錄下的 zoo_sample.cfg 為 zoo.cfg
[[email protected] conf]$ cp zoo_sample.cfg zoo.cfg
# 修改zoo.cfg
[[email protected] conf]$ vi zoo.cfg
dataDir=/opt/model/zookeeper-3.5.7/data
# zookeeper叢集配置
server.1=biubiubiu01:2888:3888
server.2=biubiubiu02:2888:3888
server.3=biubiubiu03:2888:3888
配置參數解讀:
Server.A=B:C:D。
- A 是一個數字,表示這個是第幾号伺服器;
- B 是這個伺服器的 ip 位址;
- C 是這個伺服器與叢集中的 Leader 伺服器交換資訊的端口;
- D 是萬一叢集中的 Leader 伺服器挂了,需要一個端口來重新進行選舉,選出一個新的Leader,而這個端口就是用來執行選舉時伺服器互相通信的端口。
叢集模式下配置一個檔案 myid,這個檔案在 data目錄下,這個檔案裡面有一個資料就是 A 的值,Zookeeper 啟動時讀取此檔案,拿到裡面的資料與 zoo.cfg 裡面的配置資訊比較進而判斷到底是哪個 server。
4、叢集操作
# 在data下建立myid檔案并添加資料1(重要!資料可以随便寫,
# 但是必須與檔案中添加的server對應的編号:如1相同,必須有序123、246...)
[[email protected] data]$ vi myid
1
# 将biubiubiu01配置好的zookeeper下發到biubiubiu02、biubiubiu03
[[email protected] model]$ scp -r zookeeper-3.5.7/ biubiubiu02:/opt/model
[[email protected] model]$ scp -r zookeeper-3.5.7/ biubiubiu03:/opt/model
# 注意:必須分别修改 myid 檔案中内容為 2、3
# 啟動前,可以分别配置一下環境變量,友善使用。
# 不要忘了source
5、啟動zookeeper叢集
# 分别啟動zookeeper
[[email protected] model]$ zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[[email protected] data]$ zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[[email protected] data]$ zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
# 分别jsp
[[email protected] model]$ jps
3361 Jps
3318 QuorumPeerMain
6、檢視狀态
# 檢視狀态:誰是leader,誰是follower
[[email protected] model]$ zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
[[email protected] data]$ zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
[[email protected] data]$ zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/model/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
五、用戶端指令行操作
詳細了解參數,見上邊 stat 結構體。
指令基本文法 | 功能描述 |
---|---|
help | 顯示所有操作指令 |
ls [-w] path | 使用 ls 指令來檢視目前路徑下所有子節點[-w:監聽] |
ls2 path [watch] (舊) == ls -s -w path(新) | 檢視目前節點資料并能看到更新次數等資料[-w監聽] |
create [-s] [-e] path data | 普通建立:-s 順序節點;-e 臨時節點;path 路徑;data 資料 |
get path [watch] (舊) ==get -s -w path (新) | 獲得節點的資料值[-w監聽節點資料的變化] |
set path data | 設定節點的具體值 |
stat path | 檢視節點狀态 |
delete path [version] | 删除指定路徑節點,若有子節點,必須先删子節點 |
rmr path(舊)==deleteall path | 遞歸删除 |
1、stat擷取指定節點的狀态資訊 status
2、Is某節點下的所有子節點
3、Is2是Is和stat兩個指令的結合
4、create建立節點
5、修改節點上的資料内容
6、删除節點
7、deleteall遞歸删除節點
8、Znode節點的ACL權限
傳統的linux檔案操作:檔案操作的指令+權限指令(chmod、chown)
zookeeper的權限操作(ACL:access control list):
1)節點能進行什麼操作:create、read、write、delete(前4個是對目前節點) 、admin(子節點)
2)身份的認證(4種方式):
wor1d:預設方式,相當于全世界都能通路
auth:代表已經認證通過的使用者
digest:即使用者名:密碼這種方式認證
ip:使用Ip位址認證
檢視某個節點的資料資訊: get path
檢視某個節點的權限資訊: getAcl path
基于auth的方式授權:2步
1)建立使用者
addauth digest 使用者名:密碼
2)給對應的path賦權限:
setAcl 路徑 auth:使用者名:密碼:crdwa
基于ip:setAcl /node03 ip: 127.0.0.1:cdrwa,192.168.159.191:cr,192.168.159.192:rw
六、Zookeeper API應用
1、引入依賴
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
2、代碼測試
package com.biubiubiu;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.List;
public class TestZookeeper {
public static void main(String[] args) throws Exception {
//1)建立ZookeeperClient
//sessionTimeout容忍時間,如果超過這個時間沒有連接配接到zk叢集,則會報異常,可以根據機器配置适當延長時間。
ZooKeeper zkClient = new ZooKeeper("192.168.153.231:2181,192.168.153.232:2181,192.168.153.233:2181", 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
//根據實際情況
System.out.println("執行watcher:" + event.getType() + ",path:" + event.getPath() + ",stat:" + event.getState().toString());
}
});
//2)執行操作
//2.1)測試檢視節點是否存在 //znode01
// Stat stat = zkClient.exists("/znode01", false);
// if (stat == null) {
// System.out.println("znode01節點不存在");
// } else {
// System.out.println("znode01節點存在");
// }
//2.2)建立節點
// zkClient.create("/znode01", "hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// System.out.println("建立znode01成功");
//
//2.3)檢視子清單: ls /
// List<String> nodes = zkClient.getChildren("/", false);
// for (String node : nodes) {
// System.out.println(node);
// }
//2.4)檢視某節點的資料
// byte [] data=zkClient.getData("/znode01",true,null);//null是資料的最新版本
// System.out.println("修改之前的資料是:"+new String(data));
//
// //進行修改資料
// zkClient.setData("/znode01","newDatadata".getBytes(),-1);
//
//
// byte [] data2=zkClient.getData("/znode01",true,null);//null是資料的最新版本
// System.out.println("修改之後的資料是:"+new String(data2));
//删除節點
zkClient.delete("/znode01", -1);
System.out.println("删除成功!");
zkClient.close();
}
}
覺得有幫助的,請多多支援部落客,點贊關注哦~