[分散式][zookeeper]--一起走進動物園管理員
一、ZooKeeper簡介
1. ZooKeeper是什麼
Apache ZooKeeper是一個開源的分散式服務框架,為分散式應用提供協調服務,用來解決分散式應用中的資料管理問題,如:配置管理、域名服務、分散式同步、叢集管理等
官網 https://zookeeper.apache.org/
ZooKeeper視訊教程 http://edu.51cto.com/course/16190.html
2. ZooKeeper組成
主要包括兩部分:檔案系統、通知機制
2.1 檔案系統
ZooKeeper維護一個類似Linux檔案系統的資料結構,用於儲存資料
- 資料模型結構是一種樹形結構,由許多節點構成
- 每個節點叫做ZNode(ZooKeeper Node)
- 每個節點對應一個唯一路徑,通過該路徑來標識節點,如 /app1/p_2
- 每個節點只能儲存大約1M的資料
節點型別有四種:
-
持久化目錄節點 persistent
客戶端與伺服器斷開連線,該節點仍然存在
-
持久化順序編號目錄節點 persistent_sequential
客戶端與伺服器斷開連線,該節點仍然存在,此時節點會被順序編號,如:000001、000002.....
-
臨時目錄節點 ephemeral
客戶端與伺服器斷開連線,該節點會被刪除
-
臨時順序編號目錄節點 ephemeral_sequential
客戶端與伺服器斷開連線,該節點會被刪除,此時節點會被順序編號,如:000001、000002.....
2.2 通知機制
ZooKeeper是一個基於觀察者模式設計的分散式服務管理框架
- ZooKeeper負責管理和維護專案的公共資料,並授受觀察者的註冊(訂閱)
- 一旦這些資料發生變化,ZooKeeper就會通知已註冊的觀察者
- 此時觀察者就可以做出相應的反應
簡單來說,客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化時,ZooKeeper會通知客戶端
ZooKeeper是一個訂閱中心(註冊中心)
3. 應用場景
3.1 配置管理
場景:叢集環境、伺服器的許多配置都是相同的,如:資料庫連線資訊,當需要修改這些配置時必須同時修改每臺伺服器,很麻煩
解決:把這些配置全部放到ZooKeeper上,儲存在ZooKeeper的某個目錄節點中,然後所有的應用程式(客戶端)對這個目錄節點進行監視Watch,一旦配置資訊發生變化,ZooKeeper會通知每個客戶端,然後從ZooKeeper獲取新的配置資訊,並應用到系統中。
3.2 叢集管理
場景:叢集環境下,如何知道有多少臺機器在工作?是否有機器退出或加入?需要選舉一個總管master,讓總管來管理叢集
解決:在父目錄GroupMembers下為所有機器建立臨時目錄節點,然後監聽父目錄節點的子節點變化,一旦有機器掛掉,該機器與ZooKeeper的連線斷開,其所建立的臨時目錄節點被刪除,所有其他機器都會收到通知。當有新機器加入時也是同樣的道理。
選舉master:為所有機器建立臨時順序編號目錄節點,給每臺機器編號,然後每次選取編號最小的機器作為master
3.3 負載均衡
ZooKeeper本身是不提供負載均衡策略的,需要自己實現,所以準確的說,是在負載均衡中使用ZooKeeper來做叢集的協調(也稱為軟負載均衡)
實現思路:
- 將ZooKeeper作為服務的註冊中心,所有伺服器在啟動時向註冊中心登陸自己能夠提供的服務
- 服務的呼叫者到註冊中心獲取能夠提供所需要服務的伺服器列表,然後自己根據負載均衡演算法,從中選取一臺伺服器進行連線
- 當伺服器列表發生變化時,如:某臺伺服器當機下線,或新機器加入,ZooKeeper會自動通知呼叫者重新獲取服務列表
實際上利用了ZooKeeper的特性,將ZooKeeper用為服務的註冊和變更通知中心
二、ZooKeeper安裝
1. 安裝
ZooKeeper一般都執行在Linux平臺
步驟:
-
解壓zookeeper-3.4.13.tar.gz
cd ~/software tar -zxf zookeeper-3.4.13.tar.gz
-
配置
# 建立存放資料檔案的目錄 cd zookeeper-3.4.13/ mkdir data # 建立配置檔案 cd conf cp zoo_sample.cfg zoo.cfg # 預設使用的是zoo.cfg,名稱固定 # 修改配置檔案 vi zoo.cfg dataDir=../data # 指定資料存放目錄
-
啟動zookeeper
cd bin ./zkServer.sh start | stop | status | restart # 啟動|停止|檢視狀態|重啟
-
客戶端連線zookeeper
./zkCli.sh # 啟動客戶端,預設連線本機的2181埠 或 ./zkCli.sh -server 伺服器地址:埠 # 連線指定主機、指定埠的zookeeper quit # 退出客戶端
2. 配置檔案
配置項 | 含義 | 說明 |
---|---|---|
tickTime=2000 | 心跳時間 | 維持心跳的時間間隔,單位是毫秒<br>在zookeeper中所有的時間都是以這個時間為基礎單元,進行整數倍配置 |
initLimit=10 | 初始通訊時限 | 用於zookeeper叢集,此時有多臺zookeeper伺服器,其中一個為Leader,其他都為Follower |
syncLimit=5 | 同步通訊時限 | 在執行時Leader通過心跳檢測與Follower進行通訊,如果超過syncLimit*tickTime時間還未收到響應,則認為該Follower已經當機 |
dataDir=../data | 儲存資料的目錄 | 資料檔案也稱為snapshot快照檔案 |
clientPort=2181 | 埠號 | 預設為2181 |
maxClientCnxns=60 | 單個客戶端的最大連線數限制 | 預設為60,可以設定為0,表示沒有限制 |
autopurge.snapRetainCount=3 | 保留檔案的數量 | 預設3個 |
autopurge.purgeInterval=1 | 自動清理快照檔案和事務日誌的頻率 | 預設為0,表示不開啟自動清理,單位是小時 |
dataLogDir= | 儲存日誌的目錄 | 未指定時日誌檔案也存放在dataDir中,為了效能最大化,一般建議把dataDir和dataLogDir分別放到不同的磁碟上 |
三、客戶端操作
1. 常用命令
命令 | 作用 | 說明 |
---|---|---|
help | 檢視幫助 | 檢視所有操作命令 |
ls 節點路徑 | 檢視指定節點下的內容 | |
ls2 節點路徑 | 檢視指定節點的詳細資訊 | 檢視所有子節點和當前節點的狀態 |
create 節點路徑 內容 | 建立普通節點 | 如果內容中有空格,則需要使用對雙引號引起來 |
get 節點路徑 | 獲取節點中的值 | |
create -e 節點路徑 內容 | 建立臨時節點 | 當連線斷開後,節點會被自動刪除 |
create -s 節點路徑 內容 | 建立順序編號節點 | 即帶序號的節點 |
delete 節點路徑 | 刪除節點 | 只能刪除空節點,即不能有子節點 |
rmr 節點路徑 | 遞迴刪除節點 | remove recursion |
stat 節點路徑 | 檢視節點狀態 | |
set 節點路徑 新值 | 修改節點內容 |
2. 詳解
檢視指定節點的詳細資訊: ls2 /
# 子節點名稱陣列
[zookeeper]
# -----------節點的狀態資訊,也稱為stat結構體-------------------
# 建立該znode的事務的zxid(ZooKeeper Transaction ID)
# 事務ID是ZooKeeper為每次更新操作/事務操作分配一個全域性唯一的id,表示zxid,值越小,表示越先執行
cZxid = 0x0 # 0x0表示十六進位制數0
# 建立時間
ctime = Thu Jan 01 08:00:00 CST 1970
# 最後一次更新的zxid
mZxid = 0x0
# 最後一次更新的時間
mtime = Thu Jan 01 08:00:00 CST 1970
# 最後更新的子節點的zxid
pZxid = 0x0
# 子節點的變化號,表示子節點被修改的次數,-1表示從未被修改過
cversion = -1
# 當前節點的變化號,0表示從未被修改過
dataVersion = 0
# 訪問控制列表的變化號 access control list
aclVersion = 0
# 如果臨時節點,表示當前節點的擁有者的sessionId
# 如果不是臨時節點,則值為0
ephemeralOwner = 0x0
# 資料長度
dataLength = 0
# 子節點資料
numChildren = 1
順序編號節點:
- 順序編號會緊跟在節點名稱後面,節點最終名稱為:節點名+序號,如/test0000000005
- 順序編號是一個遞增的計數器
- 順序編號是由父節點維護,從已有的子節點個數開始(包括臨時節點和被刪除的節點)
- 如果子節點為空,則從0000000000開始,依次遞增1
- 在分散式系統中,順序編號可以被用於為所有的事件進行全域性排序,這樣客戶端就可以根據序號推斷事件的順序
四、ZooKeeper叢集
1. 配置叢集
步驟:
-
準備多臺ZooKeeper伺服器
-
配置ZooKeeper伺服器
在每臺伺服器的conf/zoo.cfg檔案中新增如下內容:
server.20=192.168.4.20:2888:3888 server.21=192.168.4.21:2888:3888 server.22=192.168.4.22:2888:3888
格式:
server.A=B:C:D
- A表示這臺伺服器的編號ID,是一個數字
- B表示伺服器的IP地址或域名
- C表示這臺伺服器與叢集中的Leader交換資訊時使用的埠
- D表示執行選舉Leader伺服器時互相通訊的埠
-
建立myid配置檔案
在叢集環境下,需要在
dataDir
目錄中建立一個名為myid
的檔案,檔案內容是當前伺服器的編號ID,即上面配置的Acd data echo A的值 > myid
ZooKeeper啟動時會讀取這個檔案,將裡面的數字與zoo.cfg中配置的server.A進行比較,從而判斷這臺伺服器是哪個
-
測試叢集環境
啟動所有ZooKeeper伺服器,檢視狀態
此時在某臺伺服器上執行更新操作時,其他伺服器也會同步
2. 叢集特性
- 一個ZooKeeper叢集中,有一個領導者Leader和多個跟隨者Follower
- Leader負責進行投票的發起和決議,更新系統狀態
- Follower用於接收客戶端的請求並向客戶端返回結果,在選舉Leader過程中參與投票
- 半數機制:叢集中只要有半數以上節點存活,叢集就能夠正常工作,所以一般叢集中的伺服器個數都為奇數
- 全域性資料一致:叢集中每臺伺服器儲存一份相同的資料副本,不論客戶端連線到哪個伺服器,資料都是一致的
- 更新請求順序執行:來自同一個客戶端的更新請求,按其傳送順序依次執行
- 資料更新的原子性:一次資料更新,要麼成功,要麼失敗
- 實時性:在一定的時間範圍內,客戶端能讀取到最新資料
3. 選舉機制
ZooKeeper在提供服務時會自動選舉一個節點伺服器作為Leader,其他都是Follower
選舉流程:
- Server1啟動,給自己投票,然後傳送投票資訊,由於其它伺服器都還沒啟動,所以它發現的訊息收不到任何反饋,此時Server1為Looking狀態
- Server2啟動,給自己投票,同時與Server1通訊交換選舉結果,由於Server2的id值較大,所以Server2勝出,但由於投票數沒有過半,此時Server1和Server2都為Looking狀態
- Server3啟動,給自己投票,同時與Server1和Server2通訊交換選舉結果,由於Server3的id值較大,所以Server3勝出,此時票數已經過半,所以Server3為Leader,Server1和Server2為Follower
- Server4啟動,給自己投票,同時與Server1、Server2、Server3通訊交換選舉結果,儘管Server4的id較大,但由於叢集中已經存在Leader,所以Server4只能為Follower
- Server5啟動,同Server4類似,只能為Follower
總結:
- 每個伺服器在啟動時都會選擇自己,然後將投票資訊傳送出去
- 伺服器編號ID越大,在選擇演算法中的權重越大
- 投票數必須過半,才能選出Leader
- 誰是Leader:啟動順序的前
叢集數/2+1
個伺服器中,id值最大的會成為Leader
4. 監聽機制
4.1 監聽節點值的變化
# 在叢集的A伺服器,監聽某個節點值的變化
get /yyy watch
# 在叢集的B伺服器,修改對應節點的值
set /yyy myyyy
# 此時A伺服器會收到事件NodeDataChanged
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/yyy
監聽Watch事件是一個一次性的觸發器,當資料改變時只會觸發一次,如果以後這個資料再發生改變,則不會再次觸發
4.2 監聽節點的子節點變化
# 在叢集的A伺服器,監聽某個節點的子節點的變化
ls /yyy watch
# 在叢集的B伺服器,建立/修改/刪除對應節點的子節點
create /yyy/hello hello
# 此時A伺服器會收到事件NodeChildrenChanged
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/yyy
五、Java訪問ZooKeeper
Java操作Zookeeper很簡單,只需要新增ZooKeeper客戶端的依賴即可,可以進行節點資訊的獲取、管理等。
步驟:
-
新增jar包
<!--ZooKeeper客戶端--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.13</version> </dependency>
-
操作
public static void main(String[] args) throws IOException, KeeperException, InterruptedException { //獲取ZooKeeper的連線,即建立ZooKeeper的客戶端 String connectString = "127.0.0.1:2181"; //伺服器地址 int sessionTimeout = 3000; //超時時間,單位為毫秒 Watcher watcher = new MyWatcher(); ZooKeeper zkClient = new ZooKeeper(connectString, sessionTimeout, watcher); Thread.sleep(2000); System.out.println(zkClient.getState()); /** * 操作ZooKeeper */ //檢視指定節點下的內容 List<String> children = zkClient.getChildren("/", true);//第二個參數列示是否監視該節點 System.out.println(children); //建立節點,OPEN_ACL_UNSAFE表示acl許可權列表為完全開放,PERSISTENT表示節點型別為持久化節點 zkClient.create("/world", "世界".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //獲取節點的資料(節點的值和節點狀態Stat) byte[] data = zkClient.getData("/world", true, null); System.out.println(new String(data)); Stat stat = new Stat(); byte[] data = zkClient.getData("/hello", true, stat); byte[] data = zkClient.getData("/hello", new DataWatcher(), stat); System.out.println(new String(data)); System.out.println(stat); System.out.println(stat.getCtime()); System.out.println(stat.getVersion()); System.out.println(stat.getDataLength()); //修改節點的資料 // zkClient.setData("/hello","aaa".getBytes(),stat.getVersion()); //第三個參數列示當前節點的資料版本,一般先獲取資料stat,然後指定資料版本 zkClient.setData("/hello", "bbb".getBytes(), -1); //也可以設定為-1,表示不檢測版本 //刪除節點 zkClient.delete("/hello", -1); //判斷節點是否存在 System.out.println(zkClient.exists("/hello",false)); //存在時返回節點狀態,不存在則返回null //休眠 Thread.sleep(1000000); //關閉連線 zkClient.close(); }
ZooKeeper快速入門視訊,連結:http://edu.51cto.com/course/16190.html
相關文章
- 【zookeeper】zookeeper分散式鎖分散式
- 分散式-zookeeper分散式
- 4.5 zookeeper分散式分散式
- ZooKeeper 分散式鎖分散式
- zookeeper分散式鎖分散式
- 十九、Redis分散式鎖、Zookeeper分散式鎖Redis分散式
- Zookeeper-分散式鎖分散式
- Zookeeper(5)---分散式鎖分散式
- zookeeper 分散式鎖解析分散式
- Zookeeper — 本地完全分散式 搭建分散式
- 分散式技術-Zookeeper概述分散式
- 分散式鎖之Zookeeper實現分散式
- 【分散式】Zookeeper應用場景分散式
- 分散式鎖實現(二):Zookeeper分散式
- 6 zookeeper實現分散式鎖分散式
- ZooKeeper分散式鎖的實現分散式
- 走進阿里雲物聯網阿里
- ZooKeeper分散式專題(一) -- zookeeper安裝以及介紹分散式
- 分散式系列七: zookeeper簡單用法分散式
- 搞懂分散式技術3:初探分散式協調服務zookeeper分散式
- 搞懂分散式技術5:Zookeeper的配置與叢集管理實戰分散式
- APISpace 帶你一起走進西湖美景API
- 二十二、zookeeper實現分散式鎖分散式
- 基於zookeeper的分散式配置中心(一)分散式
- Zookeeper分散式鎖實現Curator十一問分散式
- 基於 Zookeeper 的分散式鎖實現分散式
- zookeeper 分散式鎖的原理及實現分散式
- 歡迎來到 ZooKeeper 動物世界
- 患上“遠見病”的VR,不得不走進動物世界VR
- 分散式系統理論基礎8:zookeeper分散式協調服務分散式
- ZooKeeper 分散式鎖 Curator 原始碼 04:分散式訊號量和互斥鎖分散式原始碼
- ZooKeeper分散式專題(二) -- zookeeper應用場景及資料模型分散式模型
- 關於分散式鎖原理的一些學習與思考-redis分散式鎖,zookeeper分散式鎖分散式Redis
- 一起來學習分散式鎖分散式
- Dubbo+zookeeper實現分散式服務框架分散式框架
- 基於zookeeper實現分散式配置中心(二)分散式
- 分散式協調服務☞zookeeper叢集搭建分散式
- ZooKeeper分散式配置——看這篇就夠了分散式