【Zookeeper系列】zookeeper面試題(轉)

原文連接:https://segmentfault.com/a/1190000014479433node

1.ZooKeeper是什麼?

ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,它是集羣的管理者監視着集羣中各個節點的狀態根據節點提交的反饋進行下一步合理操做。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。
客戶端的讀請求能夠被集羣中的任意一臺機器處理,若是讀請求在節點上註冊了監聽器,這個監聽器也是由所鏈接的zookeeper機器來處理。對於寫請求,這些請求會同時發給其餘zookeeper機器而且達成一致後,請求才會返回成功。所以,隨着zookeeper的集羣機器增多,讀請求的吞吐會提升可是寫請求的吞吐會降低
有序性是zookeeper中很是重要的一個特性,全部的更新都是全局有序的,每一個更新都有一個惟一的時間戳,這個時間戳稱爲zxid(Zookeeper Transaction Id)。而讀請求只會相對於更新有序,也就是讀請求的返回結果中會帶有這個zookeeper最新的zxidnginx

2.ZooKeeper提供了什麼?

一、文件系統
二、通知機制算法

3.Zookeeper文件系統

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

4.四種類型的znode

一、PERSISTENT-持久化目錄節點 
客戶端與zookeeper斷開鏈接後,該節點依舊存在 
二、PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開鏈接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號 
三、EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開鏈接後,該節點被刪除 
四、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開鏈接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號segmentfault

 

5.Zookeeper通知機制

client端會對某個znode創建一個watcher事件,當該znode發生變化時,這些client會收到zk的通知,而後client能夠根據znode變化來作出業務上的改變等。服務器

6.Zookeeper作了什麼?

一、命名服務
二、配置管理
三、集羣管理
四、分佈式鎖
五、隊列管理網絡

7.zk的命名服務(文件系統)

命名服務是指經過指定的名字來獲取資源或者服務的地址,利用zk建立一個全局的路徑,便是惟一的路徑,這個路徑就能夠做爲一個名字,指向集羣中的集羣,提供的服務的地址,或者一個遠程的對象等等。負載均衡

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

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

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

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

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

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

11.獲取分佈式鎖的流程

 


在獲取分佈式鎖的時候在locker節點下建立臨時順序節點,釋放鎖的時候刪除該臨時節點。客戶端調用createNode方法在locker下建立臨時順序節點,
而後調用getChildren(「locker」)來獲取locker下面的全部子節點,注意此時不用設置任何Watcher。客戶端獲取到全部的子節點path以後,若是發現本身建立的節點在全部建立的子節點序號最小,那麼就認爲該客戶端獲取到了鎖。若是發現本身建立的節點並不是locker全部子節點中最小的,說明本身尚未獲取到鎖,此時客戶端須要找到比本身小的那個節點,而後對其調用exist()方法,同時對其註冊事件監聽器。以後,讓這個被關注的節點刪除,則客戶端的Watcher會收到相應通知,此時再次判斷本身建立的節點是不是locker子節點中序號最小的,若是是則獲取到了鎖,若是不是則重複以上步驟繼續獲取到比本身小的一個節點並註冊監聽。當前這個過程當中還須要許多的邏輯判斷。

 

 

 

代碼的實現主要是基於互斥鎖,獲取分佈式鎖的重點邏輯在於BaseDistributedLock,實現了基於Zookeeper實現分佈式鎖的細節。

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

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

13.Zookeeper數據複製

Zookeeper做爲一個集羣提供一致的數據服務,天然,它要在全部機器間作數據複製。數據複製的好處: 
一、容錯:一個節點出錯,不致於讓整個系統中止工做,別的節點能夠接管它的工做; 
二、提升系統的擴展能力 :把負載分佈到多個節點上,或者增長節點來提升系統的負載能力; 
三、提升性能:讓客戶端本地訪問就近的節點,提升用戶訪問速度

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

對zookeeper來講,它採用的方式是寫任意。經過增長機器,它的讀吞吐能力和響應能力擴展性很是好,而寫,隨着機器的增多吞吐能力確定降低(這也是它創建observer的緣由),而響應能力則取決於具體實現方式,是延遲複製保持最終一致性,仍是當即複製快速響應

14.Zookeeper工做原理

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

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

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

16.Zookeeper 下 Server工做狀態

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

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

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

一、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會記錄事務日誌並按期進行快照,方便在恢復時進行狀態恢復。

 

二、Zookeeper選主流程(basic paxos)
fast paxos流程是在選舉過程當中,某Server首先向全部Server提議本身要成爲leader,當其它Server收到提議之後,解決epoch和 zxid的衝突,並接受對方的提議,而後向對方發送接受提議完成的消息,重複這個流程,最後必定能選舉出Leader。

 

18.Zookeeper同步流程

選完Leader之後,zk就進入狀態同步過程。 
一、Leader等待server鏈接; 
二、Follower鏈接leader,將最大的zxid發送給leader; 
三、Leader根據follower的zxid肯定同步點; 
四、完成同步後通知follower 已經成爲uptodate狀態; 
五、Follower收到uptodate消息後,又能夠從新接受client的請求進行服務了。

 

19.分佈式通知和協調

對於系統調度來講:操做人員發送通知實際是經過控制檯改變某個節點的狀態而後zk將這些變化發送給註冊了這個節點的watcher的全部客戶端
對於執行狀況彙報:每一個工做進程都在某個目錄下建立一個臨時節點並攜帶工做的進度數據,這樣彙總的進程能夠監控目錄子節點的變化得到工做進度的實時的全局狀況

20.機器中爲何會有leader?

在分佈式環境中,有些業務邏輯只須要集羣中的某一臺機器進行執行,其餘的機器能夠共享這個結果,這樣能夠大大減小重複計算提升性能,因而就須要進行leader選舉。

21.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)

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

zk的負載均衡是能夠調控,nginx只是能調權重,其餘須要可控的都須要本身寫插件;可是nginx的吞吐量比zk大不少,應該說按業務選擇用哪一種方式。

23.zookeeper watch機制

Watch機制官方聲明:一個Watch事件是一個一次性的觸發器,當被設置了Watch的數據發生了改變的時候,則服務器將這個改變發送給設置了Watch的客戶端,以便通知它們。
Zookeeper機制的特色:
一、一次性觸發數據發生改變時,一個watcher event會被髮送到client,可是client只會收到一次這樣的信息
二、watcher event異步發送watcher的通知事件從server發送到client是異步的,這就存在一個問題,不一樣的客戶端和服務器之間經過socket進行通訊,因爲網絡延遲或其餘因素致使客戶端在不通的時刻監聽到事件,因爲Zookeeper自己提供了ordering guarantee,即客戶端監聽事件後,纔會感知它所監視znode發生了變化。因此咱們使用Zookeeper不能指望可以監控到節點每次的變化。Zookeeper只能保證最終的一致性,而沒法保證強一致性
三、數據監視Zookeeper有數據監視和子數據監視getdata() and exists()設置數據監視,getchildren()設置了子節點監視。
四、註冊watcher getData、exists、getChildren
五、觸發watcher create、delete、setData
六、setData()會觸發znode上設置的data watch(若是set成功的話)。一個成功的create() 操做會觸發被建立的znode上的數據watch,以及其父節點上的child watch。而一個成功的delete()操做將會同時觸發一個znode的data watch和child watch(由於這樣就沒有子節點了),同時也會觸發其父節點的child watch。
七、當一個客戶端鏈接到一個新的服務器上時,watch將會被以任意會話事件觸發。當與一個服務器失去鏈接的時候,是沒法接收到watch的。而當client從新鏈接時,若是須要的話,全部先前註冊過的watch,都會被從新註冊。一般這是徹底透明的。只有在一個特殊狀況下,watch可能會丟失:對於一個未建立的znode的exist watch,若是在客戶端斷開鏈接期間被建立了,而且隨後在客戶端鏈接上以前又刪除了,這種狀況下,這個watch事件可能會被丟失。
八、Watch是輕量級的,其實就是本地JVM的Callback,服務器端只是存了是否有設置了Watcher的布爾類型

相關文章
相關標籤/搜索