Zookeeper 架構原理的淺嘗就止(下)

第一章   Zookeeper 的架構原理和使用

第 3 節

Zookeeper 架構原理的淺嘗就止(下)

先簡單介紹下吧,ZAB 協議全稱,ZooKeeper Atomic Broadcast,就是 ZooKeeper 原子廣播協議的意思。是 ZooKeeper 用來在集羣之間同步數據的一種協議。它是 Paxos 算法的變體,也是兩階段提交思想的一種實現。這一點大家不要弄混了。

Zookeeper 是怎麼使用 ZAB 協議的呢?其實從啓動到主從同步,崩潰恢復這些階段或者場景中,都是在 ZAB 協議的要求下進行的。

而且這些階段中,ZAB 協議會處於兩種模式下,恢復模式和消息廣播模式。恢復模式主要根據選舉算法選舉出 Leader,消息廣播模式主要保障數據同步一致性。

首先我們來看下 Zookeeper 啓動階段

Zookeeper 啓動階段,處於恢復模式,主要進行的是 Leader 選舉。因爲在 ZAB 協議中,必須有角色劃分 Leader+Follower,纔可以進行。所以必須有一個選舉算法來選舉出一臺 Zookeeper 作爲 Leader。

怎麼選舉呢?其實很簡單,就和生活中的選舉選拔一樣的方式—投票,少數服從多數。而選舉是由策略或者標準的,需要根據一些信息,選取最優的一個。比如你去中國好聲音去參賽,評委會根據你的表現等信息,決策是否選你。

其實你會發現,很多選舉都是一樣的。它們根本的邏輯就是,需要獲取信息 -> 決策 -> 得到結果。

帶着這個思想你去看 Zookeeper 的選舉,就很簡單了。當你第一次瞭解一個東西的時候,你千萬不要一開始就陷入細節,這樣很容易走偏。而是應該先摸下脈絡,在看細節,這樣重複的多了你就會發現類似的東西,會發現規律。漸漸的就會穿過現象,看透本質了。這個思想非常重要,你一定要注意這一點。

需要獲取信息,Zookeeper 的實現是,設計了這樣 3 個信息元素,如下圖所示:

知道這個關鍵的三個信息之後,就可以通過某種選舉流程進行選舉了, 最終得到結果。分析 leader 的選擇機制,zookeeper 提供了三種選舉方式,LeaderElection  、AuthFastLeaderElection、FastLeaderElection (默認)。如下圖所示。

主從同步階段,進入消息廣播模式的 2PC**+** **過半寫**

好了,你知道了 Zookeeper 啓動階段,進入恢復模式,幫 ZAB 協議選舉出了一個 Leader。接着就是進行主從數據同步階段了。

這其實就是一個兩階段提交的實現。第一次 proposal 請求算是確認網絡聯通,準備提交階段,超過一半的寫成了,就進行第二次 Commit 請求,纔是實際提交事務的階段

也就是說,當寫操作發生在 Leader 的 ZooKeeper 上後,leader 會分配一個全局唯一遞增的事務 ID(zxid)

Leader 收到寫的請求,會認爲是一種事務請求。首先 ZooKeeper 會將寫操作轉換爲事務 Proposal(提議),通過一個獨立隊列順序的同步給每個的 Follower。Follower 需要立即寫入本地磁盤日誌中,寫入成功之後就可以保證數據不會丟失,然後返回一個 ack 給 leader。如下圖所示:

當集羣中超過半數的 Follower 都確認收到事務 proposal 請求,Leader 就會再給所有的 Follower 發一個 Commit 請求,讓所有 Follower 提交這個事務請求。leader 自己也會進行 commit 操作。如下圖所示:

Zookeeper 崩潰恢復階段,進入恢復模式,重新選舉

只要集羣宕機不超過一半的機器,就可以重新選舉新的 leader。選舉過程和啓動是的選舉是類似的。

但是有幾種情況你可以好好思考下:

**情況 1:**如果一個 leader 自己剛把一個 proposal 發給部分 follower,沒有超過一半的人返回 ack,leader 是不會將 proposal 寫入本地磁盤日誌的,此時宕機.

重新選舉即可,因爲之前的那條寫 proposal 根本不算成功。

**情況 2:**如果一個 leader 自己剛把一個 proposal 寫入本地磁盤日誌,沒來得及發送給全部的 follower,就宕機了。

此時新 leader 選舉出來,它的 epoch 會自增長一位。老 leader 恢復了連接到集羣就會變成是 follower 了。此時發現自己比新 leader 多出來一條 proposal,但是自己的 epoch 比新 leader 的 epoch 低了,所以就會丟棄掉這條數據了。

**情況 3:**如果一個 leader 把一個 proposal 寫入本地磁盤日誌後,發送了一部分 commit,突然宕機了。

如果接受 commit 的 follower 沒有一個成功,肯定沒什麼影響。但是如果有任意一臺成功,此時新 leader 選舉出來的一定是 zxid 較大的,也就是有 commit 的那一臺,數據比較新,之後其他 follower 按照最新的同步一份數據過來即可。

持久化機制

Zookeeper 除了內存數據,磁盤數據一般分爲快照和事務日誌。

快照 (snapshot):記錄了整個內存中的數據,即 datatree 的 Node 數據,這個過程一般是異步的。

事務日誌 (log):實時記錄了所有訪問 zookeeper 的事務請求,包括 create、setdata、setacl、delete 等等操作;

你如果類比下其他中間件,幾乎所有中間件持久化都是類似的,都增量操作的日誌和快照兩種。比如 redis 的 aof 和 rdb。hdfs 的 fsimage 和 editLog。

你可以想下,這兩個文件的作用是什麼?肯定是爲了保障數據不丟,保障可以快速恢復數據。

Zookeeper 的持久化,你可以簡單得到,下圖所示:

日誌和快照不可能無限大,無限多。所以 Zookeeper 會創建一個異步線程,定時清理無用文件。

這裏面有很多細節實現,之後研究源碼原理時,會帶大家一一來看的。你知道它持久化有這兩個東西就行

Watcher 監聽回調機制

最後我還要強調 Zookeeper 非常重要的一個機制—Watcher 監聽回調機制**。**這裏先簡單介紹下它是個什麼意思。

Watcher 監聽回調機制,說白了就是客戶端告訴服務端它關係的 Znode 數據,當數據發生變更,服務端主動要通知客戶端,然後客戶端做一些事情的過程。按照這個理解,這個過程主要就是三步,如下圖所示:

至於具體如何註冊和觸發,以及回調的,這裏暫時不做展開,之後會詳細分析的。

小結

我們來小結下《Zookeeper 架構原理的淺嘗就止》上和下,這兩節的內容。

上一節:

Zookeeper 集羣可以支撐什麼:順序一致性、高可用、高性能和小集羣下的高併發讀寫。Zookeeper 集羣適合讀多寫少的場景。

內存數據結構和節點角色劃分:內存使用 Znode 樹形數據結構維護數據,節點主要有 Leader、Follower、Observer 三種角色。

Zookeeper 集羣通信機制:客戶端和服務端通信使用了 Java 原生的 NIO 的 API,服務端和服務端之間使用了 Java 原生的 BIO 的 API。

這一節:

基於 ZAB 協議選舉、主從同步、崩潰恢復原理:ZAB 協議是 Paxos 的變體,2PC 的一種實現。在 Zookeeper 啓動進入恢復模式,根據 zxid,serverId 等信息進行選舉出 Leader,之後進入消息廣播模式,進入主從同步狀態,在 ZAB 協議規定下,通過 2pc + 過半寫的機制保障數據一致性。最後如果崩潰的話,可以再次進入恢復模式,重新選舉 Leader。

持久化機制:快照文件和事務日誌,快照文件是異步生成的,事務日誌是實時順序寫入的。持久化文件達到限制大小,會不斷創建新文件,當然也會定時清除無用的文件,並且崩潰時可以根據持久化文件恢復數據。

Watcher 監聽回調機制:客戶端告訴服務端它關係的 Znode 數據,當數據發生變更,服務端主動要通知客戶端,然後客戶端做一些事情的過程。主要分爲了三步客戶端註冊 Watcher、服務端 Watcher 觸發、客戶端執行 Watcher 的回調。

上面這些內容其實涉及了 Zookeeper 最核心的一些原理了,你可能一時間記不住這麼多。沒關係的,之後我們會一步一步掰開了,揉碎了,仔細分析他們的。當你分析過,思考過後,相信你漸漸地就會掌握的。

好了,到這裏通過之前篇章,初步的帶大家對 Zookeeper 的架構原理進行了快速學習或者回顧,我們淺嘗就止,大家先有個大致印象就可以了。甚至這些夠你應付一些面試問題了。起碼考察 Zookeeper 的時候,從技術廣度上講,你是瞭解的了。至於技術深度的提升,就需要和我一起步入第二章一起探索了。

下一節,會給大家簡單介紹下 Zookeeper 的部署,核心參數。接着就會進入第二章,帶着大家探索 Zookeeper 的源碼世界了,請大家敬請期待吧!

PS:由於工作平常比較忙的原因,寫文章的時間可能不穩定,但每週會保證 2 更的。

金句甜點

今天的甜點是,不忘初心,找回鬥志和單純。

有些時候當你走着走着,你會發現一件事:生活會教育你,教育的你不是你自己了。比如你的鬥志很容易被人奪走。雖然古人說過,三軍可奪帥,但不可奪其志。但是很多時候,當你經歷了很多風吹雨打,你以爲你變的成熟了,變的圓滑了。但是很多時候是你失去了鬥志了。再也沒有吹牛過自己了,你會說:“我這是變的低調了”。但是其實你甚至沒有高調過。因爲高調過的人,才說可以自己低調。你可能都是趴在地下的,已經低調的再不能低了,還低什麼低了,是不是?

過去的我們很單純,但是現在反而我們變的複雜了,走着走着,很多時候摻雜了自己的東西。我們應該越學越簡單,越學越單純,千萬不要越學越複雜。其實成功很簡單,是我們把它搞複雜了,道理很簡單,是我們把它想複雜了。怎麼越來越單純呢,跟上 “瘋子” 的“傻子”會成功。你要做一個傻子,不要給人感到你很聰明。成功的人其實很多開始時候是又傻又天真的。這種才更容易成功。

剛纔我和你聊了聊鬥志和單純,爲什麼聊這個呢?是因爲,你有時候會受到別人的指點,但更多的時候還是別人的指指點點點。正常來說,你要不在乎衆人的指指點點,要在乎高人的指點。但是你經常會倒過來了,這個肯定不行。你可能特別在乎別人的指指點點,而對高人的指點置若罔聞。一路上,就是被別人的指指點點變的不是你自己了。到最後你活的不是你自己,是別人讓你活成啥樣,你就活成啥樣了。鄰居說怎麼樣的人才是好人,你變得像鄰居說的一樣。父母說你是怎樣的就好,你變得父母喜歡的樣子。你從來沒有活成你喜歡的樣子。這就是我們變成了周圍人的樣子。人生最大遺憾之一,就是活成了、變成別人喜歡的樣子。你活成你自己的喜歡的樣子,才一切都有可能。像 “瘋子” 一樣有鬥志,像 “傻子” 一樣有單純。這兩個你把它們找回來,你會活出另一個天地,另一個春天。

一個人沒有了鬥志是能看出來的,從你的眼神,單純, 是從你的表情,就比如小孩子們的表情,而不是大人們的一臉的狐疑。其實表情是最大的泄密武器。假如你在街上遇見一個算命的,他看到你表情不好,一下就能戳中你的心門,讓你心甘情願花錢算命。你應該知道,你和優秀的人在一起,你才更容易變成優秀的人。你肯定希望和成功的人,技術好的人在一起。但是你反過來想想,他們憑什麼和你在一起,你沒有鬥志的眼神,你的表情不單純。他們怎麼指點你?你沒有鬥志,他們想着先怎麼鼓勵你,你一臉狐疑,指點的話沒法給你說,因爲你的表情告訴他們,你不信他們。那他們肯定只能給你說些溫暖的話,善意的話,讓你先不懷疑。最終相信不相信,可不是你看你嘴上怎麼說的。這個下一節我們再聊,今天的金句甜點就先聊到這裏吧。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Oi5hRITyXTiBxM9zfEK8LQ