ZooKeeper學習第九期——ZooKeeper伸縮性

1、ZooKeeper中Observer

1.1 ZooKeeper角色

通過前面的介紹,我想你們都已經知道了在ZooKeeper集羣當中有兩種角色Leader和Follower。Leader能夠接受client 請求,也接收其餘Server轉發的寫請求,負責更新系統狀態。 Follower也能夠接收client請求,若是是寫請求將轉發給Leader來更新系統狀態,讀請求則由Follower的內存數據庫直接響應。 ZooKeeper集羣如圖1.1所示。數據庫

圖 1.1 ZooKeeper集羣服務服務器

但在ZooKeeper的3.3.3版本之後,ZooKeeper中又添加了一種新角色Observer。Observer的做用同Follower相似,惟一區別就是它不參與選主過程。那麼,咱們就能夠根據該特性將ZK集羣中的Server分爲兩種:網絡

(1) 投票Server:Leader、Follower性能

(2) 非投票Server:Observer測試

1.2 爲何引入Observer

(1) ZooKeeper可伸縮性優化

那麼,ZooKeeper爲何要引入Observer這個角色呢?其實在ZooKeeper中引入Observer,主要是爲了使 ZooKeeper具備更好的可伸縮性。那麼,何爲可伸縮性?關於伸縮性,對於不一樣的人意味着不一樣的事情。 而在這裏是說,若是咱們的工做負載能夠經過給系統分配更多的資源來分擔,那麼這個系統就是可伸縮的;一個不可伸縮的系統卻沒法經過增長資源來提高性能,甚 至會在工做負載增長時,性能會急劇降低。spa

在Observer出現之前,ZooKeeper的伸縮性由Follower來實現,咱們能夠經過添加Follower節點的數量來保證 ZooKeeper服務的讀性能。可是隨着Follower節點數量的增長,ZooKeeper服務的寫性能受到了影響。爲何會出現這種狀況?在此,我 們須要首先了解一下這個"ZK服務"是如何工做的。設計

(2) ZK服務過程server

ZooKeeper服務中的每一個Server可服務於多個Client,而且Client可鏈接到ZK服務中的任一臺Server來提交請求。如果讀請求,則由每臺Server的本地副本數據庫直接響應。如果改變Server狀態的寫請求,須要經過一致性協議來處理,這個協議就是咱們前面介紹的Zab協議。blog

簡單來講,Zab協議規定:來自Client的全部寫請求,都要轉發給ZK服務中惟一的ServerLeader, 由Leader根據該請求發起一個Proposal。而後,其餘的Server對該Proposal進行Vote。以後,Leader對Vote進行收 集,當Vote數量過半時Leader會向全部的Server發送一個通知消息。最後,當Client所鏈接的Server收到該消息時,會把該操做更新 到內存中並對Client的寫請求作出迴應。該工做流程以下圖1.2所示。

圖1.2 ZK 寫請求工做流程圖

從圖中咱們能夠看出, ZooKeeper 服務器在上述協議中實際扮演了兩個職能。它們一方面從客戶端接受鏈接與操做請求,另外一方面對操做結果進行投票。這兩個職能在 ZooKeeper集羣擴展的時候彼此制約。例如,當咱們但願增長 ZK服務中Client數量的時候,那麼咱們就須要增長Server的數量,來支持這麼多的客戶端。然而,從Zab協議對寫請求的處理過程當中咱們能夠發 現,增長服務器的數量,則增長了對協議中投票過程的壓力。由於Leader節點必須等待集羣中過半Server響應投票,因而節點的增長使得部分計算機運 行較慢,從而拖慢整個投票過程的可能性也隨之提升,寫操做也會隨之降低。這正是咱們在實際操做中看到的問題——隨着 ZooKeeper 集羣變大,寫操做的吞吐量會降低。

(3) ZooKeeper擴展

因此,咱們不得不,在增長Client數量的指望和咱們但願保持較好吞吐性能的指望間進行權衡。要打破這一耦合關係,咱們引入了不參與投票的服務 器,稱爲 Observer。 Observer能夠接受客戶端的鏈接,並將寫請求轉發給Leader節點。可是,Leader節點不會要求 Observer參加投票。相反,Observer不參與投票過程,僅僅在上述第3歩那樣,和其餘服務節點一塊兒獲得投票結果。

圖 1.3 Observer 寫吞吐量測試

圖1.3 顯示了一個簡單評測的結果。縱軸是,單一客戶端可以發出的每秒鐘同步寫操做的數量。橫軸是 ZooKeeper 集羣的尺寸。藍色的是每一個服務器都是投票Server的狀況,而綠色的則只有三個是投票Server,其它都是 Observer。從圖中咱們能夠看出,咱們在擴充 Observer時寫性能幾乎能夠保持不便。可是,若是擴展投票Server的數量,寫性能會明顯降低,顯然 Observers 是有效的。

這個簡單的擴展,給 ZooKeeper 的可伸縮性帶來了全新的鏡像。咱們如今能夠加入不少 Observer 節點,而無須擔憂嚴重影響寫吞吐量。但他並不是是無懈可擊的,由於協議中的通知階段,仍然與服務器的數量呈線性關係。可是,這裏的串行開銷很是低。所以,我 們能夠認爲在通知服務器階段的開銷沒法成爲主要瓶頸。

2、Observer應用

(1) Observer提高讀性能的可伸縮性

應對Client的數量增長,是 Observer的一個重要用例,可是實際上它還給集羣帶來不少其它的好處。Observer做爲ZooKeeper的一個優化,Observer服務器能夠直接獲取Leader的本地數據存儲,而無需通過投票過程。但這也面臨必定的"時光旅行"風險,也就是說:可能在讀到新值以後又讀到老值。但這隻在服務器故障時纔會發生事實上,在這種狀況下,Client能夠經過"sync"操做來保證下一個值是最新的。

所以,在大量讀操做的工做負載下,Observer會使ZooKeeper的性能獲得巨大提高。若要增長投票Server數量來承擔讀操做,那麼就 會影響ZooKeeper服務的寫性能。並且Observer容許咱們將讀性能和寫性能分開,這使ZooKeeper更適用於一些以讀爲主的應用場景。

(2) Observer提供了廣域網能力

Observer還能作更多。Observer對於跨廣域網鏈接的Client來講是很好的候選方案。Observer可做爲候選方案,緣由有三:

① 爲了得到很好的讀性能,有必要讓客戶端離服務器儘可能近,這樣往返時延不會過高。然而,將 ZooKeeper 集羣分散到兩個集羣是很是不可取的設計,由於良好配置的 ZooKeeper 應該讓投票服務器間用低時延鏈接互連——不然,咱們將會遇到上面提到的低反映速度的問題。

② 而Observer 能夠被部署在,須要訪問 ZooKeeper 的任意數據中心中。這樣,投票協議不會受到數據中心間鏈路的高時延的影響,性能獲得提高。投票過程當中 Observer 和領導節點間的消息遠少於投票服務器和領導節點間的消息。這有助於在遠程數據中心高寫負載的狀況降低低帶寬需求。

③ 因爲Observer即便失效也不會影響到投票集羣,這樣若是數據中心間鏈路發生故障,不會影響到服務自己的可用性。這種故障的發生機率要遠高於一個數據中心中機架間的鏈接的故障機率,因此不依賴於這種鏈路是個優勢。

3、ZooKeeper集羣搭建案例

前面介紹了ZooKeeper集羣中的幾種角色,接下來給你們來介紹一下如何利用這些角色,來搭建一個性能良好的ZooKeeper集羣。我以一個項目爲例,給你們分析一下該如何規劃咱們的ZooKeeper集羣。

假設咱們的項目須要進行跨機房操做,咱們的總部機房設在杭州,但他還要同美國,青島等多個機房之間進行數據交互。但機房之間的網絡延遲都比較大,好比中美機房走海底光纜有ping操做200ms的延遲,杭州和青島機房有70ms的延遲。 爲了提高系統的網絡性能,咱們在部署ZooKeeper網絡時會在每一個機房部署節點,多個機房之間再組成一個大的網絡,來保證整個ZK集羣數據一致性。

根據前面的介紹,最後的部署結構就會是:

(總部) 杭州機房  >=3臺 :由Leader/Follower構成的投票集羣

(分支) 青島機房  >=1臺 :由Observer構成的ZK集羣

(分支) 美國機房  >=1臺  : 由Observer構成的ZK集羣

圖 3.1 ZooKeeper集羣部署圖

從圖中咱們能夠看出,咱們在單個機房內組成一個投票集羣,外圍的機房都會是一個Observer集羣和投票集羣進行數據交互。 至於這樣部署的一些好處,你們本身根據我前面對ZooKeeper角色的介紹,對比着體會一下,我想這樣更能幫助你們理解ZooKeeper。並且針對這 樣的部署結構,咱們會引入一個優先集羣問題: 好比在美國機房的Client,須要優先去訪問本機房的ZK集羣,訪問不到纔去訪問HZ(總部)機房。

相關文章
相關標籤/搜索