1. 程式人生 > >《我想進大廠》之Zookeeper奪命連環9問

《我想進大廠》之Zookeeper奪命連環9問

談談你對Zookeeper的理解?

Zookeeper是一個開源的分散式協調服務,由雅虎公司建立,由於最初雅虎公司的內部研究小組的專案大多以動物的名字命名,所以後來就以Zookeeper(動物管理員)來命名了,而就是由Zookeeper來負責這些分散式元件環境的協調工作。

他的目標是可以提供高效能、高可用和順序訪問控制的能力,同時也是為了解決分散式環境下資料一致性的問題。

叢集

首先,Zookeeper叢集中有幾個關鍵的概念,Leader、Follower和Observer,Zookeeper中通常只有Leader節點可以寫入,Follower和Observer都只是負責讀,但是Follower會參與節點的選舉和過半寫成功,Observer則不會,他只是單純的提供讀取資料的功能。

通常這樣設定的話,是為了避免太多的從節點參與過半寫的過程,導致影響效能,這樣Zookeeper只要使用一個幾臺機器的小叢集就可以實現高效能了,如果要橫向擴充套件的話,只需要增加Observer節點即可。

Zookeeper建議叢集節點個數為奇數,只要超過一半的機器能夠正常提供服務,那麼整個叢集都是可用的狀態。

資料節點Znode

Zookeeper中資料儲存於記憶體之中,這個資料節點就叫做Znode,他是一個樹形結構,比如/a/b/c類似。

而Znode又分為持久節點、臨時節點、順序節點三大類。

持久節點是指只要被建立,除非主動移除,否則都應該一直儲存在Zookeeper中。

臨時節點不同的是,他的生命週期和客戶端Session會話一樣,會話失效,那麼臨時節點就會被移除。

還有就是臨時順序節點和持久順序節點,除了基本的特性之外,子節點的名稱還具有有序性。

會話Session

會話自然就是指Zookeeper客戶端和服務端之間的通訊,他們使用TCP長連線的方式保持通訊,通常,肯定會有心跳檢測的機制,同時他可以接受來自伺服器的Watch事件通知。

事件監聽器Wather

使用者可以在指定的節點上註冊Wather,這樣在事件觸發的時候,客戶端就會收到來自服務端的通知。

許可權控制ACL

Zookeeper使用ACL來進行許可權的控制,包含以下5種:

  1. CREATE,建立子節點許可權

  2. DELETE,刪除子節點許可權

  3. READ,獲取節點資料和子節點列表許可權

  4. WRITE,更新節點許可權

  5. ADMIN,設定節點ACL許可權

所以,Zookeeper通過叢集的方式來做到高可用,通過記憶體資料節點Znode來達到高效能,但是儲存的資料量不能太大,通常適用於讀多寫少的場景。

 

Zookeeper有哪些應用場景?

  1. 命名服務Name Service,依賴Zookeeper可以生成全域性唯一的節點ID,來對分散式系統中的資源進行管理。

  2. 分散式協調,這是Zookeeper的核心使用了。利用Wather的監聽機制,一個系統的某個節點狀態發生改變,另外系統可以得到通知。

  3. 叢集管理,分散式叢集中狀態的監控和管理,使用Zookeeper來儲存。

  4. Master選舉,利用Zookeeper節點的全域性唯一性,同時只有一個客戶端能夠建立成功的特點,可以作為Master選舉使用,建立成功的則作為Master。

  5. 分散式鎖,利用Zookeeper建立臨時順序節點的特性。

 

說說Wather監聽機制和它的原理?

Zookeeper可以提供分散式資料的釋出/訂閱功能,依賴的就是Wather監聽機制。

客戶端可以向服務端註冊Wather監聽,服務端的指定事件觸發之後,就會向客戶端傳送一個事件通知。

他有幾個特性:

  1. 一次性:一旦一個Wather觸發之後,Zookeeper就會將它從儲存中移除

  2. 客戶端序列:客戶端的Wather回撥處理是串行同步的過程,不要因為一個Wather的邏輯阻塞整個客戶端

  3. 輕量:Wather通知的單位是WathedEvent,只包含通知狀態、事件型別和節點路徑,不包含具體的事件內容,具體的時間內容需要客戶端主動去重新獲取資料

主要流程如下:

  1. 客戶端向服務端註冊Wather監聽

  2. 儲存Wather物件到客戶端本地的WatherManager中

  3. 服務端Wather事件觸發後,客戶端收到服務端通知,從WatherManager中取出對應Wather物件執行回撥邏輯

 

Zookeeper是如何保證資料一致性的?

Zookeeper通過ZAB原子廣播協議來實現資料的最終順序一致性,他是一個類似2PC兩階段提交的過程。

由於Zookeeper只有Leader節點可以寫入資料,如果是其他節點收到寫入資料的請求,則會將之轉發給Leader節點。

主要流程如下:

  1. Leader收到請求之後,將它轉換為一個proposal提議,並且為每個提議分配一個全域性唯一遞增的事務ID:zxid,然後把提議放入到一個FIFO的佇列中,按照FIFO的策略傳送給所有的Follower

  2. Follower收到提議之後,以事務日誌的形式寫入到本地磁碟中,寫入成功後返回ACK給Leader

  3. Leader在收到超過半數的Follower的ACK之後,即可認為資料寫入成功,就會發送commit命令給Follower告訴他們可以提交proposal了

ZAB包含兩種基本模式,崩潰恢復和訊息廣播。

整個叢集服務在啟動、網路中斷或者重啟等異常情況的時候,首先會進入到崩潰恢復狀態,此時會通過選舉產生Leader節點,當叢集過半的節點都和Leader狀態同步之後,ZAB就會退出恢復模式。之後,就會進入訊息廣播的模式。

 

那麼,Zookeeper如何進行Leader選舉的?

Leader的選舉可以分為兩個方面,同時選舉主要包含事務zxid和myid,節點主要包含LEADING\FOLLOWING\LOOKING3個狀態。

  1. 服務啟動期間的選舉

  2. 服務執行期間的選舉

 

服務啟動期間的選舉

  1. 首先,每個節點都會對自己進行投票,然後把投票資訊廣播給叢集中的其他節點

  2. 節點接收到其他節點的投票資訊,然後和自己的投票進行比較,首先zxid較大的優先,如果zxid相同那麼則會去選擇myid更大者,此時大家都是LOOKING的狀態

  3. 投票完成之後,開始統計投票資訊,如果叢集中過半的機器都選擇了某個節點機器作為leader,那麼選舉結束

  4. 最後,更新各個節點的狀態,leader改為LEADING狀態,follower改為FOLLOWING狀態

 

服務執行期間的選舉

如果開始選舉出來的leader節點宕機了,那麼執行期間就會重新進行leader的選舉。

  1. leader宕機之後,非observer節點都會把自己的狀態修改為LOOKING狀態,然後重新進入選舉流程

  2. 生成投票資訊(myid,zxid),同樣,第一輪的投票大家都會把票投給自己,然後把投票資訊廣播出去

  3. 接下來的流程和上面的選舉是一樣的,都會優先以zxid,然後選擇myid,最後統計投票資訊,修改節點狀態,選舉結束

 

那選舉之後又是怎樣進行資料同步的?

那實際上Zookeeper在選舉之後,Follower和Observer(統稱為Learner)就會去向Leader註冊,然後就會開始資料同步的過程。

資料同步包含3個主要值和4種形式。

PeerLastZxid:Learner伺服器最後處理的ZXID

minCommittedLog:Leader提議快取佇列中最小ZXID

maxCommittedLog:Leader提議快取佇列中最大ZXID

 

直接差異化同步 DIFF同步

如果PeerLastZxid在minCommittedLog和maxCommittedLog之間,那麼則說明Learner伺服器還沒有完全同步最新的資料。

  1. 首先Leader向Learner傳送DIFF指令,代表開始差異化同步,然後把差異資料(從PeerLastZxid到maxCommittedLog之間的資料)提議proposal傳送給Learner

  2. 傳送完成之後傳送一個NEWLEADER命令給Learner,同時Learner返回ACK表示已經完成了同步

  3. 接著等待叢集中過半的Learner響應了ACK之後,就傳送一個UPTODATE命令,Learner返回ACK,同步流程結束

 

先回滾再差異化同步 TRUNC+DIFF同步

這個設定針對的是一個異常的場景。

如果Leader剛生成一個proposal,還沒有來得及傳送出去,此時Leader宕機,重新選舉之後作為Follower,但是新的Leader沒有這個proposal資料。

舉個栗子:

假設現在的Leader是A,minCommittedLog=1,maxCommittedLog=3,剛好生成的一個proposal的ZXID=4,然後掛了。

重新選舉出來的Leader是B,B之後又處理了2個提議,然後minCommittedLog=1,maxCommittedLog=5。

這時候A的PeerLastZxid=4,在(1,5)之間。

那麼這一條只存在於A的提議怎麼處理?

A要進行事務回滾,相當於拋棄這條資料,並且回滾到最接近於PeerLastZxid的事務,對於A來說,也就是PeerLastZxid=3。

流程和DIFF一致,只是會先發送一個TRUNC命令,然後再執行差異化DIFF同步。

 

僅回滾同步 TRUNC同步

針對PeerLastZxid大於maxCommittedLog的場景,流程和上述一致,事務將會被回滾到maxCommittedLog的記錄。

這個其實就更簡單了,也就是你可以認為TRUNC+DIFF中的例子,新的Leader B沒有處理提議,所以B中minCommittedLog=1,maxCommittedLog=3。

所以A的PeerLastZxid=4就會大於maxCommittedLog了,也就是A只需要回滾就行了,不需要執行差異化同步DIFF了。

 

全量同步 SNAP同步

適用於兩個場景:

  1. PeerLastZxid小於minCommittedLog

  2. Leader伺服器上沒有提議快取佇列,並且PeerLastZxid不等於Leader的最大ZXID

這兩種場景下,Leader將會發送SNAP命令,把全量的資料都發送給Learner進行同步。

 

有可能會出現資料不一致的問題嗎?

還是會存在的,我們可以分成3個場景來描述這個問題。

查詢不一致

因為Zookeeper是過半成功即代表成功,假設我們有5個節點,如果123節點寫入成功,如果這時候請求訪問到4或者5節點,那麼有可能讀取不到資料,因為可能資料還沒有同步到4、5節點中,也可以認為這算是資料不一致的問題。

解決方案可以在讀取前使用sync命令。

 

leader未傳送proposal宕機

這也就是資料同步說過的問題。

leader剛生成一個proposal,還沒有來得及傳送出去,此時leader宕機,重新選舉之後作為follower,但是新的leader沒有這個proposal。

這種場景下的日誌將會被丟棄。

 

leader傳送proposal成功,傳送commit前宕機

如果傳送proposal成功了,但是在將要傳送commit命令前宕機了,如果重新進行選舉,還是會選擇zxid最大的節點作為leader,因此,這個日誌並不會被丟棄,會在選舉出leader之後重新同步到其他節點當中。

 

如果作為註冊中心,Zookeeper 和Eureka、Consul、Nacos有什麼區別?

 NacosEurekaConsulZookeeper
一致性協議 CP+AP AP CP CP
健康檢查 TCP/HTTP/MYSQL/Client Beat Client Beat TCP/HTTP/gRPC/Cmd Keep Alive
負載均衡策略 權重/ metadata/Selector Ribbon Fabio
雪崩保護
自動登出例項 支援 支援 不支援 支援
訪問協議 HTTP/DNS HTTP HTTP/DNS TCP
監聽支援 支援 支援 支援 支援
多資料中心 支援 支援 支援 不支援
跨註冊中心同步 支援 不支援 支援 不支援
SpringCloud整合 支援 支援 支援 不支援
Dubbo整合 支援 不支援 不支援 支援
K8S整合 支援 不支援 支援 不支援

 

最後,你對於CAP理論怎麼理解?

CAP是一個分散式系統設計的定理,他包含3個部分,並且最多隻能同時滿足其中兩個。

  1. Consistency一致性,因為在一個分散式系統中,資料肯定需要在不同的節點之間進行同步,就比如Zookeeper,所以一致性就是指的是資料在不同的節點之間怎樣保證一致性,對於純理論的C而言,預設的規則是忽略掉延遲的,因為如果考慮延遲的話,因為資料同步的過程無論如何都會有延遲的,延遲的過程必然會帶來資料的不一致。

  2. Availability可用性,這個指的是對於每一個請求,節點總是可以在合理的時間返回合理的響應,比如Zookeeper在進行資料同步時,無法對外提供讀寫服務,不滿足可用性要求。這裡常有的一個例子是說Zookeeper選舉期間無法提供服務不滿足A,這個說法並不準確,因為CAP關注的是資料的讀寫,選舉可以認為不在考慮範圍之內。所以,可以認為對於資料的讀寫,無論響應超時還是返回異常都可以認為是不滿足A。

  3. Partition-tolerance分割槽容錯性,因為在一個分散式系統當中,很有可能由於部分節點的網路問題導致整個叢集之間的網路不連通,所以就產生了網路分割槽,整個叢集的環境被分隔成不同的的子網,所以,一般說網路不可能100%的不產生問題,所以P一定會存在。

為什麼只能同時滿足CAP中的兩個呢?

以A\B兩個節點同步資料舉例,由於P的存在,那麼可能AB同步資料出現問題。

如果選擇AP,由於A的資料未能正確同步到B,所以AB資料不一致,無法滿足C。

如果選擇CP,那麼B就不能提供服務,就無法滿足A。

 

巨人的肩膀:

https://my.oschina.net/yunqi/blog/3040280

《從Paxos到Zookeeper分散式一致性原理與實踐》

 

&n