炒雞簡單的zookeeper初印象總結。單機安裝zookeeper集群請參考zookeeper安裝與偽集群配置。
數(shù)據(jù)結構
znode基本特性
zookeeper服務會維護一個具有層次關系的數(shù)據(jù)結構,類似于Linux文件系統(tǒng)。其中每一個節(jié)點稱為znode,如下圖所示:

每個znode包含三部分信息:
- stat. 此為狀態(tài)信息, 描述該znode的版本, 權限等信息;
- data. 與該znode關聯(lián)的數(shù)據(jù);
- children. 該znode下的子節(jié)點;
znode具有如下特性:
- 每個znode的唯一標識是路徑;
- 擁有兩種類型:永久節(jié)點(persistent)和臨時節(jié)點(ephemeral);
臨時節(jié)點:一旦創(chuàng)建這個 znode 的客戶端與服務器失去聯(lián)系,這個 znode 也將自動刪除,Zookeeper 的客戶端和服務器通信采用長連接方式,每個客戶端和服務器通過心跳來保持連接,這個連接狀態(tài)稱為 session,如果 znode 是臨時節(jié)點,這個 session 失效,znode 也就刪除了。臨時節(jié)點不能擁有子節(jié)點;- znode具有版本,也就是說一個節(jié)點可以存儲多份數(shù)據(jù);
- znode 的目錄名可以自動編號,如 App1 已經(jīng)存在,再創(chuàng)建的話,將會自動命名為 App2;
不管是永久節(jié)點還是臨時節(jié)點,均可以在創(chuàng)建時指定參數(shù)-s使得多次創(chuàng)建相同名稱的節(jié)點時按照順序自動遞增(這類節(jié)點又可以稱為sequence節(jié)點)。- znode 可以被監(jiān)控,包括這個目錄節(jié)點中存儲的數(shù)據(jù)的修改,子節(jié)點目錄的變化等,一旦變化可以通知設置監(jiān)控的客戶端,這個是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于這個特性實現(xiàn)的。
znode狀態(tài)信息
- czxid. 節(jié)點創(chuàng)建時的zxid;
- mzxid. 節(jié)點最新一次更新發(fā)生時的zxid;
- ctime. 節(jié)點創(chuàng)建時的時間戳;
- mtime. 節(jié)點最新一次更新發(fā)生時的時間戳;
- dataVersion. 節(jié)點數(shù)據(jù)的更新次數(shù);
- cversion. 其子節(jié)點的更新次數(shù);
- aclVersion. 節(jié)點ACL(授權信息)的更新次數(shù);
- ephemeralOwner. 如果該節(jié)點為ephemeral節(jié)點, ephemeralOwner值表示與該節(jié)點綁定的session id. 如果該節(jié)點不是ephemeral節(jié)點, ephemeralOwner值為0;
- dataLength. 節(jié)點數(shù)據(jù)的字節(jié)數(shù);
- numChildren. 子節(jié)點個數(shù);
zxid:
ZooKeeper狀態(tài)的每一次改變, 都對應著一個遞增的Transaction(事務) id, 該id稱為zxid. 由于zxid的遞增性質, 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2發(fā)生. 創(chuàng)建任意節(jié)點, 或者更新任意節(jié)點的數(shù)據(jù), 或者刪除任意節(jié)點, 都會導致Zookeeper狀態(tài)發(fā)生改變, 從而導致zxid的值增加。
外在表現(xiàn):分布式一致性
首先,通過一個簡單的演示來加深印象,在本機啟動了zk偽集群,啟動之后查看狀態(tài)時可以看到zoo1和zoo3是follwer的角色,zoo2是leader。zoo1對應的客戶端端口是2182,zoo2對應的端口是2183,zoo3對應的端口是2184。

然后通過zkCli -server 127.0.0.1:2182 命令連上zoo1,并通過ls /命令查看其下的節(jié)點,發(fā)現(xiàn)只有一個zookeeper節(jié)點,然后此時通過create /test "測試"命令在根目錄下創(chuàng)建一個簡單的test節(jié)點,可以看到根目錄下出現(xiàn)了test節(jié)點。
接下來退出zoo1并連接到集群中另外一臺zoo2,可以看到zoo2下面也有test節(jié)點,同樣的zoo3也有,而且內(nèi)容一致,同樣,我在任意一臺刪除test節(jié)點之后,整個集群中所有服務都會刪除test節(jié)點。

內(nèi)部機制:選主與廣播
zookeeper集群中三種角色
- 領導者(leader),負責進行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)
- 學習者(learner),包括跟隨者(follower)和觀察者(observer),follower用于接受客戶端請求并想客戶端返回結果,在選主過程中參與投票
- Observer可以接受客戶端連接,將寫請求轉發(fā)給leader,但observer不參加投票過程,只同步leader的狀態(tài),observer的目的是為了擴展系統(tǒng),提高讀取速度
zookeeper請求類型
對于exists,getData,getChildren等只讀請求,收到該請求的zk服務器將會在本地處理,因為每個服務器看到的數(shù)據(jù)結構內(nèi)容都是一致的,無所謂在哪臺機器上讀取數(shù)據(jù),因此如果ZooKeeper集群的負載是讀多寫少,并且讀請求分布得均衡的話,效率是很高的。
對于create,setData,delete等有寫操作的請求,則需要統(tǒng)一轉發(fā)給leader處理,leader需要決定編號、執(zhí)行操作,這個過程稱為一個事務(transaction)。
選主過程
當zookeeper集群啟動或者leader崩潰額時候,zk進入恢復模式,開始進行選舉。
Zk的選舉算法有兩種:一種是基于basic paxos實現(xiàn)的,另外一種是基于fast paxos算法實現(xiàn)的。系統(tǒng)默認的選舉算法為fast paxos。
basic paxos流程:
- 選舉線程由當前Server發(fā)起選舉的線程擔任,其主要功能是對投票結果進行統(tǒng)計,并選出推薦的Server;
- 選舉線程首先向所有Server發(fā)起一次詢問(包括自己);
- 選舉線程收到回復后,驗證是否是自己發(fā)起的詢問(驗證zxid是否一致),然后獲取對方的id(myid),并存儲到當前詢問對象列表中,最后獲取對方提議的leader相關信息(id,zxid),并將這些信息存儲到當次選舉的投票記錄表中;
- 收到所有Server回復以后,就計算出zxid最大的那個Server,并將這個Server相關信息設置成下一次要投票的Server;
- 線程將當前zxid最大的Server設置為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數(shù), 設置當前推薦的leader為獲勝的Server,將根據(jù)獲勝的Server相關信息設置自己的狀態(tài),否則,繼續(xù)這個過程,直到leader被選舉出來。
通過流程分析我們可以得出:要使Leader獲得多數(shù)Server的支持,則Server總數(shù)必須是奇數(shù)2n+1,且存活的Server的數(shù)目不得少于n+1.
fast paxos流程
fast paxos流程是在選舉過程中,某Server首先向所有Server提議自己要成為leader,當其它Server收到提議以后,解決epoch和 zxid的沖突,并接受對方的提議,然后向對方發(fā)送接受提議完成的消息,重復這個流程,最后一定能選舉出Leader。
接收工作流程
Leader主要有三個功能:
- 恢復數(shù)據(jù);
- 維持與Learner的心跳,接收Learner請求并判斷Learner的請求消息類型;
- Learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據(jù)不同的消息類型,進行不同的處理。
PING消息是指Learner的心跳信息;REQUEST消息是Follower發(fā)送的提議信息,包括寫請求及同步請求;ACK消息是 Follower的對提議的回復,超過半數(shù)的Follower通過,則commit該提議;REVALIDATE消息是用來延長SESSION有效時間。
Follower主要有四個功能:
- 向Leader發(fā)送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
- 接收Leader消息并進行處理;
- 接收Client的請求,如果為寫請求,發(fā)送給Leader進行投票;
- 返回Client結果。
Follower的消息循環(huán)處理如下幾種來自Leader的消息:
- PING消息:心跳消息;
- PROPOSAL消息:Leader發(fā)起的提案,要求Follower投票;
- COMMIT消息:服務器端最新一次提案的信息;
- UPTODATE消息:表明同步完成;
- REVALIDATE消息:根據(jù)Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受消息;
- SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發(fā)起,用來強制得到最新的更新。
本文參考文章: