天天看點

ZooKeeper核心原理及應用場景

為什麼會有ZooKeeper

我們知道要寫一個分布式應用是非常困難的,主要原因就是局部故障。一個消息通過網絡在兩個節點之間傳遞時,網絡如果發生故障,發送方并不知道接收方是否接收到了這個消息。有可能是收到消息以後發生了網絡故障,也有可能是沒有收到消息,又或者可能接收方的程序死了。發送方唯一的确認方法就是再次連接配接發送消息,并向他進行詢問。這就是局部故障:根本不知道操作是否失敗。是以,大部分分布式應用需要一個主要、協調控制器來管理實體分布的子程序。是以大部分應用需要開發私有的協調程式,協調程式的反複編寫浪費時間,這個時候就需要一個通用的、伸縮性好的協調器。就是因為這樣的場景,ZooKeeper應運而生,ZooKeeper的設計目的,就是為了減輕分布式應用程式所承擔的協調任務。

ZooKeeper常用的應用場景

01 / 分布式協調

分布式協調簡單說就是有人對ZooKeeper中的資料做了監聽,如果修改了ZooKeeper中被監聽的資料,ZooKeeper反過來會告訴給發起監聽的人資料的變更。比如在Kafka的設計中,Kafka的一個節點在ZooKeeper中建立了一個資料,Kafka的政策是誰建立了這個資料誰就是Kafka叢集的主節點,其餘的節點都會去監聽這個資料。如果主節點當機了,這ZooKeeper對應的資料就會發生變更,既而監聽這個資料的其餘節點就會感覺到主節點當機了,然後重新進行選舉。

02 / 中繼資料管理

很多分布式的程式需要集中式的管理自己的中繼資料,這個時候ZooKeeper就是一個很好的選擇。比如Kafka,Storm等分布式的工具就會把叢集裡核心的中繼資料存放在ZooKeeper中。

03 / 高可用

很多分布式的項目都是主從式的架構,正常情況下叢集裡有一個是主節點,其餘的都是從節點。但是如果隻有一個主節點的話,程式就會有單點故障問題,那麼這個時候就需要部署多個主節點實作高可用了,利用ZooKeeper從多個主節點中選出一個作為master,其餘的作為StandBy。比如鼎鼎大名的HDFS就是靠ZooKeeper實作的高可用。

04 / 分布式鎖

在企業裡面很多的項目需要分布式鎖,我們可以使用ZooKeeper搞分布式鎖,不過這兒大家要注意一點,ZooKeeper确實是可以搞分布式鎖的,但是ZooKeeper不支援太高的并發,也就是說如果是高并發的情況下,分布式鎖用ZooKeeper可能也不太适合,如果在高并發的情況下建議大家使用Redis去搞分布式鎖,但是并發不太高的情況下用ZooKeeper搞分布式鎖是比較友善的,也有很多人确實是這麼使用的。

ZooKeeper核心原理

01 / ZooKeeper叢集架構

ZooKeeper核心原理及應用場景

在ZooKeeper叢集當中,叢集中的伺服器角色分為leader和learner,learner又分為observer和follower,具體功能如下:

0x01、leader(上司者)

為用戶端提供讀和寫的功能,負責投票的發起和決議,叢集裡面隻有leader才能接受寫的服務。

0x02、follower(跟随者)

為用戶端提供讀服務,如果是寫的服務則轉發給leader。在選舉過程中進行投票。

0x03、observer(觀察者)

為用戶端提供讀服務,如果是寫服務就轉發個leader。不參與leader的選舉投票。也不參與寫的過半原則機制。在不影響寫的前提下,提高叢集讀的性能,此角色于zookeeper3.3系列新增的角色。

0x04、client(用戶端)

連接配接zookeeper叢集的使用者,請求的發起者,獨立于zookeeper叢集的角色。

02 / ZooKeeper讀寫機制

在ZooKeeper的選舉中,如果過半的節點都選一個節點為leader的話,那麼這個節點就會是leader節點,也就是因為這個原因,ZooKeeper叢集,隻要有過半的節點是存活的,那麼這個ZooKeeper就可以正常的提供服務。比如有5個ZooKeeper節點,其中有2個節點當機了,這個時候還有3個節點存活,存活個數超過半數,此時叢集還是正常提供服務,是以ZooKeeper叢集本生是沒有高可用問題的。又因為存活的判斷依據是超過半數,是以我們一般搭建ZooKeeper叢集的時候,都使用奇數台,這樣會比較節約機器,比如我們安裝一個6台的ZooKeeper叢集,如果當機了3台就會導緻叢集不可用,因為這個時候存活的節點數沒有超過半數了,是以6台和5台的效果是一樣的,我們用5台比較合适。

對應一個ZooKeeper叢集,我們可能有多個用戶端,用戶端能任意連接配接其中一台ZooKeeper節點,但是所有的用戶端都隻能往leader節點上面去寫資料,所有的用戶端能從所有的節點上面讀取資料。如果有用戶端連接配接的是follower節點,然後往follower上發送了寫資料的請求,這個時候follower就會把這個寫請求轉發給leader節點處理。leader接受到寫請求就會往其他節點(包括自己)同步資料,如果過半的節點接受到消息後發送回來ack消息,那麼leader節點就對這條消息進行commit,commit後該消息就對使用者可見了。因為需要過半的節點發送ack後,leader才對消息進行commit,這個時候會有一個問題,如果叢集越大,那麼等待過半節點發送回來ack消息這個過程就需要越久,也就是說節點越多雖然會增加叢集的讀性能,但是會影響到叢集的寫性能,是以我們一般建議ZooKeeper的叢集規模在3到5個節點左右。為了解決這個問題,後來的ZooKeeper中增加了一個observer 的角色,這個節點不參與投票,隻是負責同步資料。比如我們leader寫資料需要過半的節點發送ack響應,這個observer節點是不參與過半的數量統計的。它隻是負責從leader同步資料,然後提供給用戶端讀取,是以引入這個角色目的就是為了增加叢集讀的性能,然後不影響叢集的寫性能。使用者搭建叢集的時候可以自己設定該角色。

03 / Zookeeper 特點

0x01、一緻性

client用戶端無論連接配接到叢集中的哪個節點,讀到的資料都是一樣的

0x02、實時性

ZooKeeper保證用戶端在一定的時間間隔内獲得結果,包括成功和失敗,但是由于網絡延遲原因,ZooKeeper不能保證兩台用戶端同時得到剛更新的消息。如果都需要最新的消息需要調用sync()接口。

0x03、原子性

leader在同步資料的時候,同步過程保證事務性,要麼都成功,要麼都失敗。

0x04、順序性

一台伺服器上如果消息a在消息b前釋出,那麼所有的server上的消息a都是在消息b前釋出的。

04 / Zookeeper資料一緻性保證

剛剛我們看到了ZooKeeper有多個特點,但是我相信多個特點中,大家最好奇都就是Zookeeper是如何保證資料一緻性的。ZooKeeper保證資料一緻性用的是ZAB協定。通過這個協定來進行ZooKeeper叢集間的資料同步,保證資料的一緻性。

0x01、兩階段送出+過半寫機制

ZooKeeper核心原理及應用場景

ZooKeeper寫資料的機制是用戶端把寫請求發送到leader節點上(如果發送的是follower節點,follower節點會把寫請求轉發到leader節點),leader節點會把資料通過proposal請求發送到所有節點(包括自己),所有到節點接受到資料以後都會寫到自己到本地磁盤上面,寫好了以後會發送一個ack請求給leader,leader隻要接受到過半的節點發送ack響應回來,就會發送commit消息給各個節點,各個節點就會把消息放入到記憶體中(放記憶體是為了保證高性能),該消息就會使用者可見了。那麼這個時候,如果ZooKeeper要想保證資料一緻性,就需要考慮如下兩個情況,情況一:leader執行commit了,還沒來得及給follower發送commit的時候,leader當機了,這個時候如何保證消息一緻性?情況二:用戶端把消息寫到leader了,但是leader還沒發送proposal消息給其他節點,這個時候leader當機了,leader當機後恢複的時候此消息又該如何處理?

0x02、ZAB的崩潰恢複機制

針對情況一,當leader當機以後,ZooKeeper會選舉出來新的leader,新的leader啟動以後要到磁盤上面去檢查是否存在沒有commit的消息,如果存在,就繼續檢檢視其他follower有沒有對這條消息進行了commit,如果有過半節點對這條消息進行了ack,但是沒有commit,那麼新對leader要完成commit的操作。

0x03、ZAB恢複中删除資料機制

針對情況二,用戶端把消息寫到leader了,但是leader還沒發送portal消息給其他節點,這個時候leader當機了,這個時候對于使用者來說,這條消息是寫失敗的。假設過了一段時間以後leader節點又恢複了,不過這個時候角色就變為了follower了,它在檢查自己磁盤的時候會發現自己有一條消息沒有進行commit,此時就會檢測消息的編号,消息是有編号的,由高32位和低32位組成,高32位是用來展現是否發生過leader切換的,低32位就是展示消息的順序的。這個時候目前的節點就會根據高32位知道目前leader已經切換過了,是以就把目前的消息删除,然後從新的leader同步資料,這樣保證了資料一緻性。

最後

各位同學,ZooKeeper是我們學習架構的過程當中,非常非常重要的一個知識點,我們今天隻是從其中一些角度去分析的ZooKeeper,我們後面會有很多文章從不同角度深入全面的剖析ZooKeeper,幫助大家掌握ZooKeeper,歡迎大家持續關注。

繼續閱讀