ZooKeeper入门之数据模型和常用命令介绍
1、zookeeper簡介
1.1 什么是zookeeper
zookeeper官網:https://zookeeper.apache.org/
ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,后來托管到Apache,于2010年11月正式成為Apache的頂級項目。 是Hadoop和Hbase的重要組件。
分布式應用程序可以基于它實現諸如數據發布/訂閱、負載均衡、命名服務、分布式協調/通知、集群管理、Master選舉、分布式鎖和分布式隊列等功能。
1.2 應用場景
zookeeper是一個經典的分布式數據一致性解決方案,致力于為分布式應用提供一個高性能、高可用,且具有嚴格順序訪問控制能力的分布式協調存儲服務。
-
維護配置信息
-
分布式鎖服務
-
集群管理
-
生成分布式唯一ID
1.維護配置信息
java編程經常會遇到配置項,比如數據庫的url、schema、user和password等。通常這些配置項我們會放置在配置文件中,再將配置文件放置在服務器上當需要更改配置項時,需要去服務器上修改對應的配置文件。但是隨著分布式系統的興起,由于許多服務都需要使用到該配置文件,因此有必須保證該配置服務的高可用性(high availability)和各臺服務器上配置數據的一致性。通常會將配置文件部署在一個集群上,然而一個集群動輒上千臺服務器,此時如果再一臺臺服務器逐個修改配置文件那將是非常繁瑣且危險的的操作,因此就需要一種服務,能夠高效快速且可靠地完成配置項的更改等操作,并能夠保證各配置項在每臺服務器上的數據一致性。zookeeper就可以提供這樣一種服務,其使用Zab這種一致性協議來保證一致性。現在有很多開源項目使用zookeeper來維護配置,比如在hbase中,客戶端就是連接一個zookeeper,獲得必要的hbase集群的配置信息,然后才可以進一步操作。還有在開源的消息隊列kafka中,也使用zookeeper來維護broker的信息。在alibaba開源的soa框架dubbo中也廣泛的使用zookeeper管理一些配置來實現服務治理。
2. 分布式鎖服務
一個集群是一個分布式系統,由多臺服務器組成。為了提高并發度和可靠性,多臺服務器上運行著同一種服務。當多個服務在運行時就需要協調各服務的進度,有時候需要保證當某個服務在進行某個操作時,其他的服務都不能進行該操作,即對該操作進行加鎖,如果當前機器掛掉后,釋放鎖并fail over 到其他的機器繼續執行該服務。
3. 集群管理
一個集群有時會因為各種軟硬件故障或者網絡故障,出現某些服務器掛掉而被移除集群,而某些服務器加入到集群中的情況,zookeeper會將這些服務器加入/移出的情況通知給集群中的其他正常工作的服務器,以及時調整存儲和計算等任務的分配和執行等。此外zookeeper還會對故障的服務器做出診斷并嘗試修復。
4.生成分布式唯一ID
在過去的單庫單表型系統中,通常可以使用數據庫字段自帶的auto_increment屬性來自動為每條記錄生成一個唯一的ID。但是分庫分表后,就無法在依靠數據庫的auto_increment屬性來唯一標識一條記錄了。此時我們就可以用zookeeper在分布式環境下生成全局唯一ID。做法如下:每次要生成一個新Id時,創建一個持久順序節點,創建操作返回的節點序號,即為新Id,然后把比自己節點小的刪除即可
2.zookeeper的數據模型
ZooKeeper的數據節點可以視為樹狀結構(或者目錄),樹中的各節點被稱為znode(即zookeeper node),一個znode可以有多個子節點。zookeeper節點在結構上表現為樹狀;使用路徑path來定位某個znode,比如/ns-1/mysql/schema1/table1,此處ns-1、mysql、schema1、table1分別是根節點、2級節點以及3級節點;其中ns-1是mysql的父節點,mysql是ns-1的子節點。以此類推。
ZooKeeper的設計適合存儲少量的數據,并不適合存儲大量數據,所以znode的存儲限制最大不超過1M。
znode,兼具文件和目錄兩種特點。既像文件一樣維護著數據、元信息、ACL、時間戳等數據結構,又像目錄一樣可以作為路徑標識的一部分。
一個znode大體上分為3各部分:
-
節點的數據:即znode data(節點path, 節點data)的關系就像是java map中(key, value)的關系
-
節點的子節點children
-
節點的狀態stat:用來描述當前節點的創建、修改記錄,包括cZxid、ctime等
在zookeeper shell中使用get命令查看指定路徑節點的data、stat信息:
[zk: localhost:2181(CONNECTED) 5] get /motan/motan-ulive-rpc/com.uxin.zb.slive.service.SliveRoomService null cZxid = 0x50ec459 ctime = Thu Dec 12 20:55:22 CST 2019 mZxid = 0x50ec459 mtime = Thu Dec 12 20:55:22 CST 2019 pZxid = 0x1000bbbd4 cversion = 3 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 3屬性說明:
| cZxid | 數據節點創建時的事務 ID |
| ctime | 數據節點創建時的時間 |
| mZxid | 數據節點最后一次更新時的事務 ID |
| mtime | 數據節點最后一次更新時的時間 |
| pZxid | 數據節點的子節點最后一次被修改時的事務 ID |
| cversion | 子節點的更改次數 |
| dataVersion | 節點數據的更改次數 |
| aclVersion | 節點的 ACL 的更改次數 |
| ephemeralOwner | 如果節點是臨時節點,則表示創建該節點的會話的 SessionID;如果節點是持久節點,則該屬性值為 0 |
| dataLength | 數據內容的長度 |
| numChildren | 數據節點當前的子節點個數 |
3.zookeeper常用shell命令
3.1 新增節點
create [-s] [-e] path data #其中-s 為有序節點,-e 臨時節點 創建持久化節點并寫入數據:create /hadoop "123456"創建持久化有序節點,此時創建的節點名為指定節點名 + 自增序號
[zk: localhost:2181(CONNECTED) 2] create -s /a "aaa" Created /a0000000000 [zk: localhost:2181(CONNECTED) 3] create -s /b "bbb" Created /b0000000001 [zk: localhost:2181(CONNECTED) 4] create -s /c "ccc" Created /c0000000002創建臨時節點,臨時節點會在會話過期后被刪除:
[zk: localhost:2181(CONNECTED) 5] create -e /tmp "tmp" Created /tmp創建臨時有序節點,臨時節點會在會話過期后被刪除:
[zk: localhost:2181(CONNECTED) 6] create -s -e /aa 'aaa' Created /aa0000000004 [zk: localhost:2181(CONNECTED) 7] create -s -e /bb 'bbb' Created /bb0000000005 [zk: localhost:2181(CONNECTED) 8] create -s -e /cc 'ccc' Created /cc00000000063.2 更新節點
更新節點的命令是 set,可以直接進行修改,如下:
set path data [version]可以更新某個節點,也可以指定版本號更新。
[zk: localhost:2181(CONNECTED) 12] set /hadoop "345" cZxid = 0x2 ctime = Sat Oct 10 15:46:18 CST 2020 mZxid = 0xa mtime = Sat Oct 10 15:49:49 CST 2020 pZxid = 0x2 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 03.2 刪除節點
刪除節點的語法如下:
delete path [version]和更新節點數據一樣,也可以傳入版本號,當你傳入的數據版本號 (dataVersion) 和當前節點的數據版本號不符合時,zookeeper 不會執行刪除操作。
該刪除需要該節點沒有子節點存在。
[zk: localhost:2181(CONNECTED) 15] delete /hadoop 0 version No is not valid : /hadoop #無效的版本號 [zk: localhost:2181(CONNECTED) 16] delete /hadoop 1要想刪除某個節點及其所有后代節點,可以使用遞歸刪除,命令為 rmr path。
3.3 查看節點列表
查看節點列表有 ls path 和 ls2 path 兩個命令,后者是前者的增強,不僅可以查看指定路徑下的所有節點,還可以查看當前節點的信息
3.4 監聽器get path [watch]
使用 get path [watch] 注冊的監聽器能夠在節點內容發生改變的時候,向客戶端發出通知。需要注意的是 zookeeper 的觸發器是一次性的 (One-time trigger),即觸發一次后就會立即失效。
[zk: localhost:2181(CONNECTED) 4] get /hadoop watch [zk: localhost:2181(CONNECTED) 5] set /hadoop 45678 WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop ?#節點值改變3.5 監聽器stat path [watch]
使用 stat path [watch] 注冊的監聽器能夠在節點狀態發生改變的時候,向客戶端發出通知
[zk: localhost:2181(CONNECTED) 7] stat /hadoop watch [zk: localhost:2181(CONNECTED) 8] set /hadoop 112233 WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop ?#節點值改變3.6 監聽器ls || ls2 path [watch]
使用 ls path [watch] 或 ls2 path [watch] 注冊的監聽器能夠監聽該節點下所有子節點的增加和刪除操作。
[zk: localhost:2181(CONNECTED) 9] ls /hadoop watch [] [zk: localhost:2181(CONNECTED) 10] create /hadoop/yarn "aaa" WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/hadoop4.zookeeper的數據一致性
Zab協議介紹:https://www.jianshu.com/p/2bceacd60b8a
在ensemble集群中follower的update操作會滯后于leader的update完成。事實的結果使我們在提交更新數據之前,不必在每一臺ZooKeeper服務器上執行持久化變更數據,而是僅需在主服務器上執行持久化變更數據。ZooKeeper客戶端的最佳實踐是全部鏈接到follower上。然而客戶端是有可能連接到leader上的,并且客戶端控制不了這個選擇,甚至客戶端并不知道連接到了follower還是leader。下圖所示, 讀操作向follower請求即可,而寫操作由leader來提交。
?
每一個對znode樹的更新操作,都會被賦予一個全局唯一的ID,我們稱之為zxid(ZooKeeper Transaction ID)。更新操作的ID按照發生的時間順序升序排序。例如, z1小于 z2,那么 z1的操作就早于 z2操作。
ZooKeeper在數據一致性上實現了如下幾個方面:
-
順序一致性
從客戶端提交的更新操作是按照先后循序排序的。例如,如果一個客戶端將一個znode z賦值為a,然后又將z的值改變成b,那么在這個過程中不會有客戶端在z的值變為b后,取到的值是a。
-
原子性
更新操作的結果不是失敗就是成功。即,如果更新操作失敗,其他的客戶端是不會知道的。
-
系統視圖唯一性
無論客戶端連接到哪個服務器,都將看見唯一的系統視圖。如果客戶端在同一個會話中去連接一個新的服務器,那么 他所看見的視圖的狀態不會比之前服務器上看見的更舊。當ensemble中的一個服務器宕機,客戶端去嘗試連接另外一臺服務器時,如果這臺服務器的狀態舊于之前宕機的服務器,那么服務器將不會接受客戶端的連接請求,直到服務器的狀態趕上之前宕機的服務器為止。
-
持久性
一旦更新操作成功,數據將被持久化到服務器上,并且不能撤銷。所以服務器宕機重啟,也不會影響數據。
-
時效性
系統視圖的狀態更新的延遲時間是有一個上限的,最多不過幾十秒。如果服務器的狀態落后于其他服務器太多,ZooKeeper會寧可關閉這個服務器上的服務,強制客戶端去連接一個狀態更新的服務器。
總結
以上是生活随笔為你收集整理的ZooKeeper入门之数据模型和常用命令介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kafka在ZooKeeper中的应用
- 下一篇: CSS样式相关汇总