大數據面試系列之——Zookeeper

1.簡單介紹下Zookeeper

ZooKeeper是一個開放源碼的分佈式協調服務,它是集羣的管理者,監視着集羣中各個節點的狀態根據節點提交的反饋進行下一步合理操作。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。

分佈式應用程序可以基於Zookeeper實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master選舉、分佈式鎖和分佈式隊列等功能。

Zookeeper保證瞭如下分佈式一致性特性:

順序一致性
原子性
單一視圖
可靠性
實時性(最終一致性)

客戶端的讀請求可以被集羣中的任意一臺機器處理,如果讀請求在節點上註冊了監聽器,這個監聽器也是由所連接的zookeeper機器來處理。對於寫請求,這些請求會同時發給其他zookeeper機器並且達成一致後,請求才會返回成功。因此,隨着zookeeper的集羣機器增多,讀請求的吞吐會提高但是寫請求的吞吐會下降。

有序性是zookeeper中非常重要的一個特性,所有的更新都是全局有序的,每個更新都有一個唯一的時間戳,這個時間戳稱爲zxid(Zookeeper Transaction Id)。而讀請求只會相對於更新有序,也就是讀請求的返回結果中會帶有這個zookeeper最新的zxid。

2.Zookeeper提供了什麼

  • 1.文件系統
  • 2.通知機制

3.Zookeeper的文件系統

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

4.四種類型的znode

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

5.Zookeeper的通知機制

client端會對某個znode建立一個watcher事件,當該znode發生變化時,這些client會收到zk的通知,然後client可以根據znode變化來做出業務上的改變等。

6.Zookeeper做了什麼

  • 1、命名服務
  • 2、配置管理
  • 3、集羣管理
  • 4、分佈式鎖
  • 5、隊列管理

7.Zookeeper的命名服務

命名服務是指通過指定的名字來獲取資源或者服務的地址,利用zk創建一個全局的路徑,即是唯一的路徑,這個路徑就可以作爲一個名字,指向集羣中的集羣,提供的服務的地址,或者一個遠程的對象等等。

8.Zookeeper的配置管理(文件系統、通知機制)

程序分佈式的部署在不同的機器上,將程序的配置信息放在zk的znode下,當有配置發生改變時,也就是znode發生變化時,可以通過改變zk中某個目錄節點的內容,利用watcher通知給各個客戶端,從而更改配置。

9.Zookeeper集羣管理(文件系統、通知機制)

所謂集羣管理無在乎兩點:是否有機器退出和加入、選舉master。
對於第一點,所有機器約定在父目錄下創建臨時目錄節點,然後監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與 zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,於是,所有人都知道:它上船了。
新機器加入也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了,對於第二點,我們稍微改變一下,所有機器創建臨時順序編號目錄節點,每次選取編號最小的機器作爲master就好。

10.Zookeeper Watcher 機制 – 數據變更通知

Zookeeper允許客戶端向服務端的某個Znode註冊一個Watcher監聽,當服務端的一些指定事件觸發了這個Watcher,服務端會向指定客戶端發送一個事件通知來實現分佈式的通知功能,然後客戶端根據Watcher通知狀態和事件類型做出業務上的改變。

工作機制:

  • 客戶端註冊watcher
  • 服務端處理watcher
  • 客戶端回調watcher

Watcher特性總結:

  • 1.一次性
    無論是服務端還是客戶端,一旦一個Watcher被觸發,Zookeeper都會將其從相應的存儲中移除。這樣的設計有效的減輕了服務端的壓力,不然對於更新非常頻繁的節點,服務端會不斷的向客戶端發送事件通知,無論對於網絡還是服務端的壓力都非常大。

  • 2.客戶端串行執行
    客戶端Watcher回調的過程是一個串行同步的過程。

  • 3.輕量

    • Watcher通知非常簡單,只會告訴客戶端發生了事件,而不會說明事件的具體內容。
    • 客戶端向服務端註冊Watcher的時候,並不會把客戶端真實的Watcher對象實體傳遞到服務端,僅僅是在客戶端請求中使用boolean類型屬性進行了標記。
  • 4.watcher event異步發送watcher的通知事件從server發送到client是異步的,這就存在一個問題,不同的客戶端和服務器之間通過socket進行通信,由於網絡延遲或其他因素導致客戶端在不通的時刻監聽到事件,由於Zookeeper本身提供了ordering guarantee,即客戶端監聽事件後,纔會感知它所監視znode發生了變化。所以我們使用Zookeeper不能期望能夠監控到節點每次的變化。Zookeeper只能保證最終的一致性,而無法保證強一致性。

  • 5.註冊watcher getData、exists、getChildren

  • 6.觸發watcher create、delete、setData

  • 7.當一個客戶端連接到一個新的服務器上時,watch將會被以任意會話事件觸發。當與一個服務器失去連接的時候,是無法接收到watch的。而當client重新連接時,如果需要的話,所有先前註冊過的watch,都會被重新註冊。通常這是完全透明的。只有在一個特殊情況下,watch可能會丟失:對於一個未創建的znode的exist watch,如果在客戶端斷開連接期間被創建了,並且隨後在客戶端連接上之前又刪除了,這種情況下,這個watch事件可能會被丟失。

11.客戶端註冊Watcher實現

  • 1.調用getData()/getChildren()/exist()三個API,傳入Watcher對象
  • 2.標記請求request,封裝Watcher到WatchRegistration
  • 3.封裝成Packet對象,發服務端發送request
  • 4.收到服務端響應後,將Watcher註冊到ZKWatcherManager中進行管理
  • 5.請求返回,完成註冊。

12.服務端處理Watcher實現

  • 1.服務端接收Watcher並存儲
    接收到客戶端請求,處理請求判斷是否需要註冊Watcher,需要的話將數據節點的節點路徑和ServerCnxn(ServerCnxn代表一個客戶端和服務端的連接,實現了Watcher的process接口,此時可以看成一個Watcher對象)存儲在WatcherManager的WatchTable和watch2Paths中去。

  • 2.Watcher觸發
    以服務端接收到 setData() 事務請求觸發NodeDataChanged事件爲例:

    • 封裝WatchedEvent
    • 將通知狀態(SyncConnected)、事件類型(NodeDataChanged)以及節點路徑封裝成一個WatchedEvent對象
    • 查詢Watcher
      從WatchTable中根據節點路徑查找Watcher
    • 沒找到;說明沒有客戶端在該數據節點上註冊過Watcher
    • 找到;提取並從WatchTable和Watch2Paths中刪除對應Watcher(從這裏可以看出Watcher在服務端是一次性的,觸發一次就失效了)
  • 3.調用process方法來觸發Watcher
    這裏process主要就是通過ServerCnxn對應的TCP連接發送Watcher事件通知。

13.客戶端回調Watcher

客戶端SendThread線程接收事件通知,交由EventThread線程回調Watcher。客戶端的Watcher機制同樣是一次性的,一旦被觸發後,該Watcher就失效了。

14.Zookeeper分佈式鎖(文件系統、通知機制)

有了zookeeper的一致性文件系統,鎖的問題變得容易。鎖服務可以分爲兩類,一個是保持獨佔,另一個是控制時序。
對於第一類,我們將zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。用完刪除掉自己創建的distribute_lock 節點就釋放出鎖。
對於第二類, /distribute_lock 已經預先存在,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除,依次方便。

15.獲取分佈式鎖的流程

在這裏插入圖片描述在獲取分佈式鎖的時候在locker節點下創建臨時順序節點,釋放鎖的時候刪除該臨時節點。客戶端調用createNode方法在locker下創建臨時順序節點,
然後調用getChildren(“locker”)來獲取locker下面的所有子節點,注意此時不用設置任何Watcher。客戶端獲取到所有的子節點path之後,如果發現自己創建的節點在所有創建的子節點序號最小,那麼就認爲該客戶端獲取到了鎖。如果發現自己創建的節點並非locker所有子節點中最小的,說明自己還沒有獲取到鎖,此時客戶端需要找到比自己小的那個節點,然後對其調用exist()方法,同時對其註冊事件監聽器。之後,讓這個被關注的節點刪除,則客戶端的Watcher會收到相應通知,此時再次判斷自己創建的節點是否是locker子節點中序號最小的,如果是則獲取到了鎖,如果不是則重複以上步驟繼續獲取到比自己小的一個節點並註冊監聽。當前這個過程中還需要許多的邏輯判斷。

在這裏插入圖片描述
代碼的實現主要是基於互斥鎖,獲取分佈式鎖的重點邏輯在於BaseDistributedLock,實現了基於Zookeeper實現分佈式鎖的細節。

16.Zookeeper隊列管理(文件系統、通知機制)

兩種類型的隊列:
1、同步隊列,當一個隊列的成員都聚齊時,這個隊列纔可用,否則一直等待所有成員到達。
2、隊列按照 FIFO 方式進行入隊和出隊操作。
第一類,在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。
第二類,和分佈式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。在特定的目錄下創建PERSISTENT_SEQUENTIAL節點,創建成功時Watcher通知等待的隊列,隊列刪除序列號最小的節點用以消費。此場景下Zookeeper的znode用於消息存儲,znode存儲的數據就是消息隊列中的消息內容,SEQUENTIAL序列號就是消息的編號,按序取出即可。由於創建的節點是持久化的,所以不必擔心隊列消息的丟失問題。

17.服務器角色

Leader

事務請求的唯一調度和處理者,保證集羣事務處理的順序性
集羣內部各服務的調度者

Follower

處理客戶端的非事務請求,轉發事務請求給Leader服務器
參與事務請求Proposal的投票
參與Leader選舉投票

Observer

3.3.0版本以後引入的一個服務器角色,在不影響集羣事務處理能力的基礎上提升集羣的非事務處理能力

處理客戶端的非事務請求,轉發事務請求給Leader服務器
不參與任何形式的投票

18.Zookeeper 下 Server工作狀態

每個Server在工作過程中有三種狀態:
LOOKING:當前Server不知道leader是誰,正在搜尋
LEADING:當前Server即爲選舉出來的leader
FOLLOWING:leader已經選舉出來,當前Server與之同步

19.zookeeper是如何選取主leader的?

當leader崩潰或者leader失去大多數的follower,這時zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的Server都恢復到一個正確的狀態。Zk的選舉算法有兩種:一種是基於basic paxos實現的,另外一種是基於fast paxos算法實現的。系統默認的選舉算法爲fast paxos。

1、Zookeeper選主流程(basic paxos)

(1)選舉線程由當前Server發起選舉的線程擔任,其主要功能是對投票結果進行統計,並選出推薦的Server;
(2)選舉線程首先向所有Server發起一次詢問(包括自己);
(3)選舉線程收到回覆後,驗證是否是自己發起的詢問(驗證zxid是否一致),然後獲取對方的id(myid),並存儲到當前詢問對象列表中,最後獲取對方提議的leader相關信息(id,zxid),並將這些信息存儲到當次選舉的投票記錄表中;
(4)收到所有Server回覆以後,就計算出zxid最大的那個Server,並將這個Server相關信息設置成下一次要投票的Server;
(5)線程將當前zxid最大的Server設置爲當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數,設置當前推薦的leader爲獲勝的Server,將根據獲勝的Server相關信息設置自己的狀態,否則,繼續這個過程,直到leader被選舉出來。 通過流程分析我們可以得出:要使Leader獲得多數Server的支持,則Server總數必須是奇數2n+1,且存活的Server的數目不得少於n+1. 每個Server啓動後都會重複以上流程。在恢復模式下,如果是剛從崩潰狀態恢復的或者剛啓動的server還會從磁盤快照中恢復數據和會話信息,zk會記錄事務日誌並定期進行快照,方便在恢復時進行狀態恢復。

在這裏插入圖片描述

2、Zookeeper選主流程(fast paxos)

fast paxos流程是在選舉過程中,某Server首先向所有Server提議自己要成爲leader,當其它Server收到提議以後,解決epoch和 zxid的衝突,並接受對方的提議,然後向對方發送接受提議完成的消息,重複這個流程,最後一定能選舉出Leader。
在這裏插入圖片描述

20.Zookeeper同步流程

選完Leader以後,zk就進入狀態同步過程。
1、Leader等待server連接;
2、Follower連接leader,將最大的zxid發送給leader;
3、Leader根據follower的zxid確定同步點;
4、完成同步後通知follower 已經成爲uptodate狀態;
5、Follower收到uptodate消息後,又可以重新接受client的請求進行服務了。

在這裏插入圖片描述

21.zookeeper是如何保證事務的順序一致性的?

zookeeper採用了全局遞增的事務Id來標識,所有的proposal(提議)都在被提出的時候加上了zxid,zxid實際上是一個64位的數字,高32位是epoch(時期; 紀元; 世; 新時代)用來標識leader週期,如果有新的leader產生出來,epoch會自增,低32位用來遞增計數。當新產生proposal的時候,會依據數據庫的兩階段過程,首先會向其他的server發出事務執行請求,如果超過半數的機器都能執行並且能夠成功,那麼就會開始執行。

22.Zookeeper數據複製

Zookeeper作爲一個集羣提供一致的數據服務,自然,它要在所有機器間做數據複製。數據複製的好處:
1、容錯:一個節點出錯,不致於讓整個系統停止工作,別的節點可以接管它的工作;
2、提高系統的擴展能力 :把負載分佈到多個節點上,或者增加節點來提高系統的負載能力;
3、提高性能:讓客戶端本地訪問就近的節點,提高用戶訪問速度。

從客戶端讀寫訪問的透明度來看,數據複製集羣系統分下面兩種:
1、寫主(WriteMaster) :對數據的修改提交給指定的節點。讀無此限制,可以讀取任何一個節點。這種情況下客戶端需要對讀與寫進行區別,俗稱讀寫分離;
2、寫任意(Write Any):對數據的修改可提交給任意的節點,跟讀一樣。這種情況下,客戶端對集羣節點的角色與變化透明。

對zookeeper來說,它採用的方式是寫任意。通過增加機器,它的讀吞吐能力和響應能力擴展性非常好,而寫,隨着機器的增多吞吐能力肯定下降(這也是它建立observer的原因),而響應能力則取決於具體實現方式,是延遲複製保持最終一致性,還是立即複製快速響應。

23.Zookeeper工作原理

Zookeeper 的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。

24.分佈式通知和協調

對於系統調度來說:操作人員發送通知實際是通過控制檯改變某個節點的狀態,然後zk將這些變化發送給註冊了這個節點的watcher的所有客戶端。
對於執行情況彙報:每個工作進程都在某個目錄下創建一個臨時節點。並攜帶工作的進度數據,這樣彙總的進程可以監控目錄子節點的變化獲得工作進度的實時的全局情況。

25.機器中爲什麼會有leader?

在分佈式環境中,有些業務邏輯只需要集羣中的某一臺機器進行執行,其他的機器可以共享這個結果,這樣可以大大減少重複計算,提高性能,於是就需要進行leader選舉。

26.zk節點宕機如何處理?

Zookeeper本身也是集羣,推薦配置不少於3個服務器。Zookeeper自身也要保證當一個節點宕機時,其他節點會繼續提供服務。
如果是一個Follower宕機,還有2臺服務器提供訪問,因爲Zookeeper上的數據是有多個副本的,數據並不會丟失;
如果是一個Leader宕機,Zookeeper會選舉出新的Leader。
ZK集羣的機制是隻要超過半數的節點正常,集羣就能正常提供服務。只有在ZK節點掛得太多,只剩一半或不到一半節點能工作,集羣才失效。
所以
3個節點的cluster可以掛掉1個節點(leader可以得到2票>1.5)
2個節點的cluster就不能掛掉任何1個節點了(leader可以得到1票<=1)

27.zookeeper負載均衡和nginx負載均衡區別

zk的負載均衡是可以調控,nginx只是能調權重,其他需要可控的都需要自己寫插件;但是nginx的吞吐量比zk大很多,應該說按業務選擇用哪種方式。

28.Zookeeper工作流程-Leader

1)恢復數據
2)維持與learner的心跳,接收learner請求並判斷learner的請求消息類型
3)learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據不同的消息類型,進行不同的處理。
PING消息是指Learner的心跳信息;
REQUEST消息是指Follower發送的提議信息,包括寫請求及同步請求;
ACK消息是Follower的對提議的回覆,超過半數的Follower通過,則commit該提議;
REVALIDATE消息是用來延長SESSION有效時間。

在這裏插入圖片描述

29.Zookeeper工作流程-Follower

Follower主要有四個功能:
1)向leader發送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息)
2)接收leader消息並進行處理
3)接收Client的請求,如果爲寫請求,發送給Leader進行投票
4)返回Client結果
Follower的消息循環處理如下幾種來自Leader的消息:
1)PING消息:心跳信息;
2)PROPOSAL消息:Leader發起的提案,要求Follwer投票;
3)COMMIT消息:服務端最新一次提案的信息;
4)UPTODATE消息:表名同步完成;
5)REVALIDATE消息:根據Leader的REVALIDATE結果,關閉等待revalidate的session還是允許其接收消息;
6)SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。

在這裏插入圖片描述

30.Zookeeper的角色描述

在這裏插入圖片描述

31.集羣最少要幾臺機器,集羣規則是怎樣的?

集羣規則爲2N+1臺,N>0,即3臺。

32.集羣支持動態添加機器嗎?

其實就是水平擴容了,Zookeeper在這方面不太好。兩種方式:

  • 全部重啓:關閉所有Zookeeper服務,修改配置之後啓動。不影響之前客戶端的會話。
  • 逐個重啓:在過半存活即可用的原則下,一臺機器重啓不影響整個集羣對外提供服務。這是比較常用的方式。

3.5版本開始支持動態擴容。

33.Zookeeper對節點的watch監聽通知是永久的嗎?爲什麼不是永久的?

不是。官方聲明:一個Watch事件是一個一次性的觸發器,當被設置了Watch的數據發生了改變的時候,則服務器將這個改變發送給設置了Watch的客戶端,以便通知它們。

爲什麼不是永久的,舉個例子,如果服務端變動頻繁,而監聽的客戶端很多情況下,每次變動都要通知到所有的客戶端,給網絡和服務器造成很大壓力。
一般是客戶端執行getData(“/節點A”,true),如果節點A發生了變更或刪除,客戶端會得到它的watch事件,但是在之後節點A又發生了變更,而客戶端又沒有設置watch事件,就不再給客戶端發送。
在實際應用中,很多情況下,我們的客戶端不需要知道服務端的每一次變動,我只要最新的數據即可。

34.Zookeeper的java客戶端都有哪些?

java客戶端:zk自帶的zkclient及Apache開源的Curator。

35.chubby是什麼,和zookeeper比你怎麼看?

chubby是google的,完全實現paxos算法,不開源。zookeeper是chubby的開源實現,使用zab協議,paxos算法的變種。

36.說幾個zookeeper常用的命令

常用命令:ls get set create delete等。

37.ZAB和Paxos算法的聯繫與區別?

  • 相同點:
    • 兩者都存在一個類似於Leader進程的角色,由其負責協調多個Follower進程的運行
    • Leader進程都會等待超過半數的Follower做出正確的反饋後,纔會將一個提案進行提交
    • ZAB協議中,每個Proposal中都包含一個 epoch 值來代表當前的Leader週期,Paxos中名字爲Ballot
  • 不同點:
    • ZAB用來構建高可用的分佈式數據主備系統(Zookeeper),Paxos是用來構建分佈式一致性狀態機系統。

38.Zookeeper的典型應用場景

Zookeeper是一個典型的發佈/訂閱模式的分佈式數據管理與協調框架,開發人員可以使用它來進行分佈式數據的發佈和訂閱。

通過對Zookeeper中豐富的數據節點進行交叉使用,配合Watcher事件通知機制,可以非常方便的構建一系列分佈式應用中年都會涉及的核心功能,如:

  • 數據發佈/訂閱
  • 負載均衡
  • 命名服務
  • 分佈式協調/通知
  • 集羣管理
  • Master選舉
  • 分佈式鎖
  • 分佈式隊列
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章