zookeeper之深入理解其原理

1 zookeeper基礎

1.1 基本瞭解

  • zookeeper是一個類似hdfs的樹形文件結構, zookeeper可以用來保證數據在(zk)集羣之間的數據的事務性一致
  • 分佈、開源的應用程序協調服務,它是集羣的管理者,監視着集羣中各個節點的狀態,根據節點的反饋進行下一步合理操作。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。
  • 主要解決分佈式應用經常遇到的數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。
  • Zookeeper 作爲 Hadoop 項目中的一個子項目,是 Hadoop 集羣管理的一個必不可少的模塊,它主要用來控制集羣中的數據,如它管理 Hadoop集羣中的NameNode,還有HbaseMaster Election、Server 之間狀態同步等

1.2 角色與功能

1.2.1 角色

1.2.1.1 三種角色

  • 領導者(leader),負責進行投票的發起和決議,更新系統狀態
  • 學習者(learner),包括跟隨者(follower)和觀察者(observer
    follower用於接受客戶端請求並想客戶端返回結果,在選主過程中參與投票
    Observer可以接受客戶端連接,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態
    observer的目的是爲了擴展系統提高讀取速度
  • 客戶端(client)請求發起方:
    在這裏插入圖片描述

1.2.1.2 爲什麼引入Observer

  • Zookeeper需保證高可用和強一致性,爲了支持更多的客戶端,需要增加更多Server
    Server增多,投票階段延遲增大,影響性能;權衡伸縮性高吞吐率,引入Observer
  • Observer不參與投票;
  • Observers接受客戶端的連接,並將寫請求轉發給leader節點;
  • 加入更多Observer節點,提高伸縮性,同時不影響吞吐率

1.2.2 角色的功能

  • Leader主要功能:恢復數據、維持與Follower的心跳;接收Follower請求並判斷Follower的請求消息類型
    Leader的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據不同的消息類型,進行不同的處理。
  • Follower主要功能:向Leader發送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);接收Leader消息並進行處理;接收Client的請求,如果爲寫請求,發送給Leader進行投票;返回Client結果

不同的消息類型:

  • PING消息是指Leader的心跳信息;
  • PROPOSAL消息:Leader發起的提案,要求Follower投票;
  • COMMIT消息:服務器端最新一次提案的信息;
  • REQUEST消息是Follower發送的提議信息,包括寫請求同步請求
  • ACK消息是Follower的對提議的回覆,超過半數的Follower通過,則commit該提議
  • REVALIDATE消息是用來延長SESSION有效時間。
  • UPTODATE消息:表明同步完成;
  • SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。

1.3 zookeeper提供了什麼

1.3.1 文件系統

Zookeeper提供一個多層級的節點命名空間(節點稱爲znode)。
與文件系統不同的是,這些節點都可以設置關聯的數據,而文件系統中只有文件節點可以存放數據而目錄節點不行。
Zookeeper爲了保證高吞吐低延遲,在內存中維護了這個樹狀的目錄結構,這種特性使得Zookeeper不能用於存放大量的數據,每個節點的存放數據上限爲1M
在這裏插入圖片描述
Znode分爲四種類型:

  • PERSISTENT持久化目錄節點。(客戶端與zookeeper斷開連接後,該節點依舊存在)。
  • PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點。(客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號)
  • EPHEMERAL-臨時目錄節點(客戶端與zookeeper斷開連接後,該節點被刪除)
  • EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點。(客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號)

1.4 Zookeeper的核心及原理

1.4.1 zookeeper特性

  • 一致性client不論連接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。
  • 可靠性:具有簡單、健壯、良好的性能,如果消息m被到一臺服務器接受,那麼它將被所有的服務器接受。
  • 實時性Zookeeper保證客戶端將在一個時間間隔範圍內獲得服務器的更新信息,或者服務器失效的信息。但由於網絡延時等原因,Zookeeper不能保證兩個客戶端能同時得到剛更新的數據,如果需要最新數據,應該在讀數據之前調用sync()接口。
  • 等待無關wait-free):慢的或者失效的client不得干預快速的client的請求,使得每個client都能有效的等待。
  • 原子性:更新只能成功或者失敗,沒有中間狀態。
  • 順序性:包括全局有序偏序兩種:全局有序是指如果在一臺服務器上消息a在消息b前發佈,則在所有Server上消息a都將在消息b前被髮布;偏序是指如果一個消息b在消息a後被同一個發送者發佈,a必將排在b前面。

1.4.2 zookeeper原理

Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。
Zab協議有兩種模式,它們分別是恢復模式(選主)廣播模式(同步)

  • 當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leaderServer具有相同的系統狀態。
  • 消息廣播模式:在ZooKeeper中所有的事務請求都由一個主服務器也就是Leader來處理,其他服務器爲FollowerLeader將客戶端的事務請求轉換爲事務Proposal,並且將Proposal分發給集羣中其他所有的Follower,然後Leader等待Follwer反饋,當有過半數(>=N/2+1)的Follower反饋信息後,Leader將再次向集羣內Follower廣播Commit信息,Commit爲將之前的Proposal提交。

廣播模式需要保證proposal被按順序處理,爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxidzxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數

一旦leader已經和多數的follower進行了狀態同步後,他就可以開始廣播消息了,即進入廣播狀態。這時候當一個server加入zookeeper服務中,它會在恢復模式下啓動,發現leader,並和leader進行狀態同步。待到同步結束,它也參與消息廣播。Zookeeper服務一直維持在Broadcast狀態,直到leader崩潰了或者leader失去了大部分的followers支持。

每個Server在工作過程中有三種狀態:

  • LOOKING:當前Server不知道leader是誰,正在搜尋。
  • LEADING:當前Server即爲選舉出來的leader
  • FOLLOWINGleader已經選舉出來,當前Server與之同步

1.5 zookeeper流程

1.5.1 數據流程

在這裏插入圖片描述

  1. ClientFollwer發出一個寫的請求
  2. Follwer把請求發送給Leader
  3. Leader接收到以後開始發起投票並通知Follwer進行投票
  4. Follwer把投票結果發送給Leader
  5. Leader將結果彙總後如果需要寫入,則開始寫入同時把寫入操作通知給Follwer,然後commit;
  6. Follwer把請求結果返回給Client

1.5.2 選主流程以及算法

1.5.2.1 選舉leader

leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的server都恢復到一個正確的狀態。 
每個Server啓動以後都詢問其它的Server它要投票給誰。
對於其他server的詢問,server每次根據自己的狀態都回復自己推薦的leaderid和上一次處理事務的zxid(系統啓動時每個server都會推薦自己)
收到所有Server回覆以後,就計算出zxid最大的哪個Server,並將這個Server相關信息設置成下一次要投票的Server
計算這過程中獲得票數最多的的sever爲獲勝者,如果獲勝者的票數超過半數,則改server被選爲leader。否則,繼續這個過程,直到leader被選舉出來,leader就會開始等待server連接
Follower連接leader,將最大的zxid發送給leaderLeader根據followerzxid確定同步點
完成同步後通知follower 已經成爲uptodate狀態
Follower收到uptodate消息後,又可以重新接受client的請求進行服務了

1.5.2.2 選舉算法

Zk的選舉算法有兩種:一種是基於basic paxos實現的,另外一種是基於fast paxos算法實現的。系統默認的選舉算法爲fast paxos

1.5.2.2.1 Basic paxos

Basic paxos:當前Server發起選舉的線程,向所有Server發起詢問,選舉線程收到所有回覆,計算zxid最大Server,並推薦此爲leader,若此提議獲得n/2+1票通過,此爲leader,否則重複上述流程,直到leader選出。

1.5.2.2.2 Fast paxos

Fast paxos:某Server首先向所有Server提議自己要成爲leader,當其它Server收到提議以後,解決epochzxid的衝突,並接受對方的提議,然後向對方發送接受提議完成的消息,重複這個流程,最後一定能選舉出Leader。(即提議方解決其他所有epochzxid的衝突,即爲leader)

1.6 ZooKeeper的Watcher機制

client端會對某個znode建立一個watcher事件,當該znode發生變化時,這些client會收到zk的通知,然後client可以根據znode變化來做出業務上的改變等
ZooKeeperWatcher 機制主要包括客戶端線程客戶端 WatchManagerZooKeeper 服務器三部分。
在這裏插入圖片描述

  • ZooKeeper:部署在遠程主機上的 ZooKeeper 集羣,當然,也可能是單機的。
  • Client :分佈在各處的 ZooKeeper 的 jar 包程序,被引用在各個獨立應用程序中。
  • WatchManager:一個接口,用於管理各個監聽器,只有一個方法 materialize(),返回一個Watcherset

客戶端在向 ZooKeeper 服務器註冊 Watcher 的同時,會將Watcher對象存儲在客戶端的 WatchManager中。當ZooKeeper 服務器觸發 Watcher 事件後,會向客戶端發送通知,客戶端線程從WatchManager 的實現類中取出對應的 Watcher對象來執行回調邏輯。

Watcher 特性總結

  • 一次性
    無論是服務端還是客戶端,一旦一個 Watcher被觸發,ZooKeeper都會將其從相應的存儲中移除。因此,在 Watcher 的使用上,需要反覆註冊。這樣的設計有效地減輕了服務端的壓力。
  • 客戶端串行執行
    客戶端 Watcher 回調的過程是一個串行同步的過程,這爲我們保證了順序,同時,需要注意的一點是,一定不能因爲一個Watcher 的處理邏輯影響了整個客戶端的Watcher回調,所以,覺得客戶端 Watcher的實現類要另開一個線程進行處理業務邏輯,以便給其他的 Watcher調用讓出時間。
  • 輕量
    WatcherEventZooKeeper整個Watcher通知機制的最小通知單元,這個數據結構中只包含三部分內容:通知狀態、事件類型和節點路徑。也就是說,Watcher 通知非常簡單,只會告訴客戶端發生了事件,而不會說明事件的具體內容。例如針對 NodeDataChanged 事件,ZooKeeperWatcher 只會通知客戶端指定數據節點的數據內容發生了變更,而對於原始數據以及變更後的新數據都無法從這個事件中直接獲取到,而是需要客戶端主動重新去獲取數據——這也是 ZooKeeperWatcher 機制的一個非常重要的特性

2 zookeeper的作用

2.1 命名服務

zookeeper的文件系統裏創建一個目錄,即有唯一的path。在我們使用tborg無法確定上游程序的部署機器時即可與下游程序約定好path,通過path即能互相探索發現。

2.2 配置管理

把應用配置放置zookeeper上去,保存在 Zookeeper的某個目錄節點中,然後所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然後從Zookeeper 獲取新的配置信息應用到系統中就好。

2.3 集羣管理

節點(機器)增刪及Master選取。

2.3.1 節點增刪

所有機器約定在父目錄GroupMembers下創建臨時目錄節點,然後監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,於是,所有人都知道:它掛了。新機器加入 也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了。

2.3.1 Master節點選取

所有機器創建臨時順序編號目錄節點,每次選取編號最小的機器作爲master就好。
如果有多個master,每次只能有一個master負責主要的工作,其他的master作爲備份,同時對負責工作的master進行監聽,一旦負責工作的master掛掉了,其他的master就會收到監聽的事件,從而去搶奪負責工作的權利,其他沒有爭奪到負責主要工作的master轉而去監聽負責工作的新master,簡而言之:一人幹,多人看

2.4 分佈式鎖

基於zookeeper一致性文件系統,實現鎖服務。鎖服務分爲保存獨佔時序控制兩類。

2.4.1 保存獨佔

zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。
所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。
用完刪除自己創建的distribute_lock節點就釋放鎖。

2.4.2 時序控制

基於/distribute_lock鎖,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除,依次方便。

2.5 隊列管理

同步隊列,FIFO隊列(入隊與出隊)

2.5.1 同步隊列

當一個隊列的成員都聚齊時,這個隊列纔可用,否則一直等待所有成員到達。在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目

2.5.2 FIFO隊列

FIFO隊列(入隊與出隊)和分佈式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。

2.6 分佈式與數據複製

Zookeeper作爲一個集羣提供一致的數據服務,必然在所有機器間做數據複製。
數據複製好處:

  • 容錯:一個節點出錯,不致於讓整個系統停止工作,別的節點可以接管它的工作。
  • 提高系統的擴展能力:把負載分佈到多個節點上,或者增加節點來提高系統的負載能力;
  • 性能提升:讓客戶端本地訪問就近節點,提高用戶訪問速度。

3 數據一致性與paxos 算法

3.1 數據集羣

數據集羣系統分:

  • 寫主(writeMaster),對數據的修改提交給指定的節點。讀無此限制,可以讀取任何一個節點。這種情況下客戶端需要對讀與寫進行區別,俗稱讀寫分離;
  • 寫任意(對數據的修改可提交給任意的節點,跟讀一樣。這種情況下,客戶端對集羣節點的角色與變化透明)對zookeeper來說,它採用的方式是寫任意。通過增加機器,它的讀吞吐能力和響應能力擴展性非常好,而寫,隨着機器的增多吞吐能力肯定下降(這也是它建立observer的原因),而響應能力則取決於具體實現方式,是延遲複製保持最終一致性,還是立即複製快速響應。

3.2 原則

在一個分佈式數據庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。Paxos算法解決:保證每個節點執行相同的操作序列。

Paxos算法通過投票來對寫操作進行全局編號,同一時刻,只有一個寫操作被批准,同時併發的寫操作要去爭取選票,只有獲得過半數選票的寫操作纔會被 批准(所以永遠只會有一個寫操作得到批准),其他的寫操作競爭失敗只好再發起一輪投票,就這樣,在日復一日年復一年的投票中,所有寫操作都被嚴格編號排序。編號嚴格遞增,當一個節點接受了一個編號爲100的寫操作,之後又接受到編號爲99的寫操作(因爲網絡延遲等很多不可預見原因),它馬上能意識到自己數據不一致了,自動停止對外服務並重啓同步過程。任何一個節點掛掉都不會影響整個集羣的數據一致性(總2n+1臺,除非掛掉大於n臺)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章