zookeeper(下文簡寫為zk)大家都不陌生。但是,看到很多同學對zookeeper的理解過於程式化,有些地方甚至需要背,是大可不必的。把本質理解了,概念性和功能介紹都可以推出來的,而且架構要活學活用,透過現象看本質,才能對技術和技術領悟有大的提升。下面來看下zk的功能及本質。
zookeeper的定義及用途
我們先了解官方的定義。
Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination.
Apache ZooKeeper 是一個致力於開發和維護開源服務器,該服務器實現高可用的分布式協調框架。
ZooKeeper is a high-performance coordination service for distributed applications. It exposes common services - such as naming, configuration management, synchronization, and group services - in a simple interface so you don't have to write them from scratch.
zookeeper是一個高性能的分布式應用協調服務框架。它以簡單接口形式實現了一系列的通用服務,比如** 命名、配置管理、同步、分組 **等,因此你不必從一堆草稿中去實現他們.
zookeeper的本質功能
通過官方的定義介紹,我們知道了zk是一個server,擅長分布式協調功能。我們來分析下功能的本質實現是怎樣的。
zk的數據模型是以znode的形式存儲和組織。與標准文件系統類似,是一個樹形結構,根節點是'/'。
圖中每個節點都是一個znode,類似於文件系統中的一個文件,形成了一個樹形結構,每個znode內部還可以存儲不超過1M的數據。這些znode可以是持久的,還可以是短期的(ephemeral )。
短期的(ephemeral )znode當創建他的客戶端session超時,會被zk主動刪除。有點類似給文件加鎖,進程異常退出后,鎖立刻解除。
zk的數據模型類似文件系統,這點也沒什么特別的。本質還是kv形式,如果kv的value還要求是kv格式,那么就和zk的數據模型一樣。表示成樹形的格式,更容易表示層級關系。
zk的特別之處在於:
0. zk內部的選主和寫數據機制。有超過一半的zk集群節點選出來的主節點,成為集群的leader節點,負責主寫和同步其他叢屬follower節點。底層用的ZAB(ZooKeeper Atomic Broadcast)協議。
- 短期的(ephemeral )znode功能。方便實現鎖類操作,在分布式中處理超時狀態。
- 客戶端可以設置監控watch某個znode的功能,當znode發生變化(版本號變更)時,會主動通知watch的客戶端有變化了。該功能讓客戶端不必輪詢,能夠有序地知道znode變更順序。
命名、配置管理、同步、分組等功能,都是通過1、2兩點結合實現的。我們自研的業務如果想實現,也都能想到,或者用類似方式實現。
zk內部的選主和寫數據機制。就不那么容易想了,只能依靠論文實現。所以這點更要好好學習下,這種方法很有特點,並且不容易想出來,也不容易理解。
與已有自研業務的區別
自研業務中,實現zk功能的,比較像的是配置中心(下文簡稱cc)。
一般實現cc,采用一主多從,主節點負責寫,從節點只讀。主節點通過binlog同步從節點,保證最終一致性。
主節點有兩個寫數據途徑:
1、通過管理台的配置中心更新配置表;
2、通過客戶端api上報服務狀態,更新客戶端節點負載和健康狀況。
3、把心跳和變更回包作為一個協議,通知客戶端配置更新。
如果從節點死機,不影響集群服務,對應的客戶端尋找新的從節點去讀。
如果主節點死機,cc只提供讀服務,要人工來恢復。
影響:故障期間不能新增或修改配置以及配置項的負載。
如果用zk來實現cc,在正常情況下運行方式和cc是一樣的。但是當主死機后,會用算法重新選出主,對客戶端透明。讓主節點死機停寫的概率降低。但是如果有一半的節點死掉,會造成整個zk集群不可用。
對比:
自研cc | zk | |
---|---|---|
選主方式 | 人工配置,主死了集群只讀,人工介入恢復 | 集群協商選主,自恢復后繼續服務 |
集群完全不可用條件 | 所有節點都死掉 | 一半節點死掉(可能有分區問題造成zk內部同步有問題,但是節點是可以服務的) |
zk的選主方式,並沒有完勝一主多從的所有場景。
- 算法比較復雜,不容易理解和實現。
- 某些重要任務,出現主寫問題,為了一致性,要人工介入恢復,自動選新主切換會造成數據丟失。
- 對於業務特定的場景特點,做一些彌補方案,能降低單點主寫的風險。例如搭建多套cc,並行寫,都對外提供服務,因為配置節點健康和負載的少量不一致,對業務來說是可以接受的。還可以在業務中增加緩存,保證主死了能夠有足夠的時間恢復。
以上自研業務沒有引入ZAB或paxos協議的原因。在出現zk之后,想用的業務可以直接在zk之上構建集群內節點選主功能。
注意事項
我們在zk上構建服務的時候,要注意zk死一半節點就全集群死掉的特點。要考慮到如果zk集群不服務,業務有備選方案,能夠對外盡力服務。例如zk充當配置中心,client要設置緩存,或默認配置。
為了節約資源,zk集群必須是奇數台機器。但是zk的機器數變多,對性能會有較大影響。寫數據同步和選主都會變得越來越慢。
解決方法:
- 讀多寫少:增加觀察者節點來擴展讀性能。觀察者節點不參與主從節點的協商和選舉,只負責同步主節點。
- 讀少寫多:根據業務特點划分set,做到平行擴展。
總結
zookeeper通過ZAB協議實現了集群內部選主和寫同步功能,提高了服務的健壯性,和寫操作的有序性。是實現的難點,背后有嚴密的數學理論推理。
通過實現,短期的(ephemeral )znode和主動通知節點變更消息的功能,客戶端能夠及時知道監聽節點變化,在客戶端和zk斷開連接后,也能夠自動釋放節點。輕松地實現鎖類服務和監聽更新類需求。這些是實現名字服務、配置管理、同步、分組等服務的基礎。
轉載請注明來源:深入淺出zookeeper之一:功能及本質
本文鏈接地址:https://www.owenzhang.net/blog/121.html