您好,登錄后才能下訂單哦!
本篇內容介紹了“Zookeeper面試常見的問題有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現(Chubby是不開源的),它是集群的管理者,監視著集群中各個節點的狀態根據節點提交的反饋進行下一步合理操作。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶 。
Zookeeper一個最常用的使用場景就是用于擔任服務生產者和服務消費者的注冊中心,服務生產者將自己提供的服務注冊到Zookeeper中心,服務的消費者在進行服務調用的時候先到Zookeeper中查找服務,獲取到服務生產者的詳細信息之后,再去調用服務生產者的內容與數據,簡單示例圖如下:
ZooKeeper 的架構圖中我們需要了解和掌握的主要有:
(1)ZooKeeper分為服務器端(Server) 和客戶端(Client),客戶端可以連接到整個 ZooKeeper服務的任意服務器上(除非 leaderServes 參數被顯式設置, leader 不允許接受客戶端連接)。
(2)客戶端使用并維護一個 TCP 連接,通過這個連接發送請求、接受響應、獲取觀察的事件以及發送信息。如果這個 TCP 連接中斷,客戶端將自動嘗試連接到另外的 ZooKeeper服務器。客戶端第一次連接到 ZooKeeper服務時,可以接受這個連接的 ZooKeeper服務器會為這個客戶端建立一個會話。當這個客戶端連接到另外的服務器時,這個會話會被新的服務器重新建立。
(3)上圖中每一個Server代表一個安裝Zookeeper服務的機器,即是整個提供Zookeeper服務的集群(或者是由偽集群組成);
(4)組成ZooKeeper服務的服務器必須彼此了解。它們維護一個內存中的狀態圖像,以及持久存儲中的事務日志和快照, 只要大多數服務器可用,ZooKeeper服務就可用;
(5)ZooKeeper 啟動時,將從實例中選舉一個 leader,Leader 負責處理數據更新等操作,一個更新操作成功的標志是當且僅當大多數Server在內存中成功修改數據。每個Server 在內存中存儲了一份數據。
(6)Zookeeper是可以集群復制的,集群間通過Zab協議(Zookeeper Atomic Broadcast)來保持數據的一致性;
(7)Zab協議包含兩個階段:leader election階段和Atomic Brodcast階段。
a) 集群中將選舉出一個leader,其他的機器則稱為follower,所有的寫操作都被傳送給leader,并通過brodcast將所有的更新告訴給follower。
b) 當leader崩潰或者leader失去大多數的follower時,需要重新選舉出一個新的leader,讓所有的服務器都恢復到一個正確的狀態。
c) 當leader被選舉出來,且大多數服務器完成了 和leader的狀態同步后,leadder election 的過程就結束了,就將會進入到Atomic brodcast的過程。
d) Atomic Brodcast同步leader和follower之間的信息,保證leader和follower具有形同的系統狀態。
Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。
Zab協議有兩種模式,它們 分別是恢復模式(選主)和廣播模式(同步)。
Zab協議 的全稱是 Zookeeper Atomic Broadcast** (Zookeeper原子廣播)。Zookeeper 是通過 Zab 協議來保證分布式事務的最終一致性。Zab協議要求每個 Leader 都要經歷三個階段:發現,同步,廣播。
當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
為了保證事務的順序一致性,zookeeper采用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加 上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一 個新的epoch,標識當前屬于那個leader的統治時期。第32位用于遞增計數。
epoch:可以理解為皇帝的年號,當新的皇帝leader產生后,將有一個新的epoch年號。
每個Server在工作過程中有三種狀態:
LOOKING:當前Server不知道leader是誰,正在搜尋。
LEADING:當前Server即為選舉出來的leader。
FOLLOWING:leader已經選舉出來,當前Server與之同步。
ZooKeeper設計的目的是提供高性能、高可用、順序一致性的分布式協調服務、保證數據最終一致性。
高性能(簡單的數據模型)
采用樹形結構組織數據節點;
全量數據節點,都存儲在內存中;
Follower 和 Observer 直接處理非事務請求;
高可用(構建集群)
半數以上機器存活,服務就能正常運行
自動進行 Leader 選舉
順序一致性(事務操作的順序)
每個事務請求,都會轉發給 Leader 處理
每個事務,會分配全局唯一的遞增id(zxid,64位:epoch + 自增 id)
最終一致性
通過提議投票方式,保證事務提交的可靠性
提議投票方式,只能保證 Client 收到事務提交成功后,半數以上節點能夠看到最新數據
系統模型:
領導者(leader)
Leader服務器為客戶端提供讀服務和寫服務。負責進行投票的發起和決議,更新系統狀態。
學習者(learner)
跟隨者(follower) Follower服務器為客戶端提供讀服務,參與Leader選舉過程,參與寫操作“過半寫成功”策略。
觀察者(observer) Observer服務器為客戶端提供讀服務,不參與Leader選舉過程,不參與寫操作“過半寫成功”策略。用于在不影響寫性能的前提下提升集群的讀性能。
客戶端(client):服務請求發起方。
節點有哪些類型?
Znode兩種類型:
持久的(persistent):客戶端和服務器端斷開連接后,創建的節點不刪除(默認)。
短暫的(ephemeral):客戶端和服務器端斷開連接后,創建的節點自己刪除。
Znode有四種形式:
持久化目錄節點(PERSISTENT):客戶端與Zookeeper斷開連接后,該節點依舊存在持久化順序編號目錄節點(PERSISTENT_SEQUENTIAL)
客戶端與Zookeeper斷開連接后,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號:臨時目錄節點(EPHEMERAL)
客戶端與Zookeeper斷開連接后,該節點被刪除:臨時順序編號目錄節點(EPHEMERAL_SEQUENTIAL)
客戶端與Zookeeper斷開連接后,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
「注意」:創建ZNode時設置順序標識,ZNode名稱后會附加一個值,順序號是一個單調遞增的計數器,由父節點維護。
節點屬性有哪些
一個znode節點不僅可以存儲數據,還有一些其他特別的屬性。接下來我們創建一個/test節點分析一下它各個屬性的含義。
[zk: localhost:2181(CONNECTED) 6] get /test 456 cZxid = 0x59ac // ctime = Mon Mar 30 15:20:08 CST 2020 mZxid = 0x59ad mtime = Mon Mar 30 15:22:25 CST 2020 pZxid = 0x59ac cversion = 0 dataVersion = 2 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0
屬性說明
Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。leader選舉是保證分布式數據一致性的關鍵。
出現選舉主要是兩種場景:初始化、leader不可用。
當zk集群中的一臺服務器出現以下兩種情況之一時,就會開始leader選舉。
服務器初始化啟動。
服務器運行期間無法和leader保持連接。
而當一臺機器進入leader選舉流程時,當前集群也可能處于以下兩種狀態。
集群中本來就已經存在一個leader。
集群中確實不存在leader。
首先第一種情況,通常是集群中某一臺機器啟動比較晚,在它啟動之前,集群已經正常工作,即已經存在一臺leader服務器。當該機器試圖去選舉leader時,會被告知當前服務器的leader信息,它僅僅需要和leader機器建立連接,并進行狀態同步即可。
重點是leader不可用了,此時的選主制度。
投票信息中包含兩個最基本的信息。
sid:即server id,用來標識該機器在集群中的機器序號。
zxid:即zookeeper事務id號。
ZooKeeper狀態的每一次改變, 都對應著一個遞增的Transaction id,,該id稱為zxid.,由于zxid的遞增性質, 如果zxid1小于zxid2,,那么zxid1肯定先于zxid2發生。創建任意節點,或者更新任意節點的數據, 或者刪除任意節點,都會導致Zookeeper狀態發生改變,從而導致zxid的值增加。
以(sid,zxid)的形式來標識一次投票信息。
例如:如果當前服務器要推舉sid為1,zxid為8的服務器稱為leader,那么投票信息可以表示為(1,8)
集群中的每臺機器發出自己的投票后,也會接受來自集群中其他機器的投票。每臺機器都會根據一定的規則,來處理收到的其他機器的投票,以此來決定是否需要變更自己的投票。
規則如下:
初始階段,都會給自己投票。
當接收到來自其他服務器的投票時,都需要將別人的投票和自己的投票進行pk,規則如下:
優先檢查zxid。zxid比較大的服務器優先作為leader。如果zxid相同的話,就比較sid,sid比較大的服務器作為leader。
簡單地說:client端會對某個znode 注冊一個watcher事件,當該znode發生變化時,這些client會收到ZooKeeper的通知,然后client可以根據znode變化來做出業務上的改變等。
經典使用場景:zookeeper為dubbo提供服務的注冊與發現,作為注冊中心,但是大家有沒有想過zookeeper為啥能夠實現服務的注冊與發現嗎?
這就不得不說一下zookeeper的靈魂 Watcher(監聽者)。
什么是watcher?
watcher 是zooKeeper中一個非常核心功能 ,客戶端watcher 可以監控節點的數據變化以及它子節點的變化,一旦這些狀態發生變化,zooKeeper服務端就會通知所有在這個節點上設置過watcher的客戶端 ,從而每個客戶端都很快感知,它所監聽的節點狀態發生變化,而做出對應的邏輯處理。
簡單的介紹了一下watcher ,那么我們來分析一下,zookeeper是如何實現服務的注冊與發現。zookeeper的服務注冊與發現,主要應用的是zookeeper的znode節點數據模型和watcher機制,大致的流程如下:
服務注冊:服務提供者(Provider)啟動時,會向zookeeper服務端注冊服務信息,也就是創建一個節點,例如:用戶注冊服務com.xxx.user.register,并在節點上存儲服務的相關數據(如服務提供者的ip地址、端口等)。
服務發現:服務消費者(Consumer)啟動時,根據自身配置的依賴服務信息,向zookeeper服務端獲取注冊的服務信息并設置watch監聽,獲取到注冊的服務信息之后,將服務提供者的信息緩存在本地,并進行服務的調用。
服務通知:一旦服務提供者因某種原因宕機不再提供服務之后,客戶端與zookeeper服務端斷開連接,zookeeper服務端上服務提供者對應服務節點會被刪除(例如:用戶注冊服務com.xxx.user.register),隨后zookeeper服務端會異步向所有消費用戶注冊服務com.xxx.user.register,且設置了watch監聽的服務消費者發出節點被刪除的通知,消費者根據收到的通知拉取最新服務列表,更新本地緩存的服務列表。
上邊的過程就是zookeeper可以實現服務注冊與發現的大致原理。
watcher有哪些類型?
znode節點可以設置兩類watch,一種是DataWatches,基于znode節點的數據變更從而觸發 watch 事件,觸發條件getData()、exists()、setData()、 create()。
另一種是Child Watches,基于znode的孩子節點發生變更觸發的watch事件,觸發條件 getChildren()、 create()。
而在調用 delete() 方法刪除znode時,則會同時觸發Data Watches和Child Watches,如果被刪除的節點還有父節點,則父節點會觸發一個Child Watches。
watcher有什么特性?
watch對節點的監聽事件是一次性的!客戶端在指定的節點設置了監聽watch,一旦該節點數據發生變更通知一次客戶端后,客戶端對該節點的監聽事件就失效了。
如果還要繼續監聽這個節點,就需要我們在客戶端的監聽回調中,再次對節點的監聽watch事件設置為True。否則客戶端只能接收到一次該節點的變更通知。
數據發布與訂閱
發布與訂閱即所謂的配置管理,顧名思義就是將數據發布到ZooKeeper節點上,供訂閱者動態獲取數據,實現配置信息的集中式管理和動態更新。例如全局的配置信息,地址列表等就非常適合使用。
數據發布/訂閱的一個常見的場景是配置中心,發布者把數據發布到 ZooKeeper 的一個或一系列的節點上,供訂閱者進行數據訂閱,達到動態獲取數據的目的。
配置信息一般有幾個特點:
數據量小的KV
數據內容在運行時會發生動態變化
集群機器共享,配置一致
ZooKeeper 采用的是推拉結合的方式。
推: 服務端會推給注冊了監控節點的客戶端 Wathcer 事件通知
答: 客戶端獲得通知后,然后主動到服務端拉取最新的數據
命名服務
作為分布式命名服務,命名服務是指通過指定的名字來獲取資源或者服務的地址,利用ZooKeeper創建一個全局的路徑,這個路徑就可以作為一個名字,指向集群中的集群,提供的服務的地址,或者一個遠程的對象等等。
統一命名服務的命名結構圖如下所示:
1、在分布式環境下,經常需要對應用/服務進行統一命名,便于識別不同服務。
類似于域名與IP之間對應關系,IP不容易記住,而域名容易記住。
通過名稱來獲取資源或服務的地址,提供者等信息。
2、按照層次結構組織服務/應用名稱。
可將服務名稱以及地址信息寫到ZooKeeper上,客戶端通過ZooKeeper獲取可用服務列表類。
配置管理
程序分布式的部署在不同的機器上,將程序的配置信息放在ZooKeeper的znode下,當有配置發生改變時,也就是znode發生變化時,可以通過改變zk中某個目錄節點的內容,利用watch通知給各個客戶端 從而更改配置。
ZooKeeper配置管理結構圖如下所示:
1、分布式環境下,配置文件管理和同步是一個常見問題。
一個集群中,所有節點的配置信息是一致的,比如 Hadoop 集群。
對配置文件修改后,希望能夠快速同步到各個節點上。
2、配置管理可交由ZooKeeper實現。
可將配置信息寫入ZooKeeper上的一個Znode。
各個節點監聽這個Znode。
一旦Znode中的數據被修改,ZooKeeper將通知各個節點。
集群管理
所謂集群管理就是:是否有機器退出和加入、選舉master。
集群管理主要指集群監控和集群控制兩個方面。前者側重于集群運行時的狀態的收集,后者則是對集群進行操作與控制。開發和運維中,面對集群,經常有如下需求:
希望知道集群中究竟有多少機器在工作
對集群中的每臺機器的運行時狀態進行數據收集
對集群中機器進行上下線的操作
集群管理結構圖如下所示:
分布式環境中,實時掌握每個節點的狀態是必要的,可根據節點實時狀態做出一些調整。
可交由ZooKeeper實現。
可將節點信息寫入ZooKeeper上的一個Znode。
監聽這個Znode可獲取它的實時狀態變化。
3、典型應用
Hbase中Master狀態監控與選舉。
利用ZooKeeper的強一致性,能夠保證在分布式高并發情況下節點創建的全局唯一性,即:同時有多個客戶端請求創建 /currentMaster 節點,最終一定只有一個客戶端請求能夠創建成功
分布式通知與協調
1、分布式環境中,經常存在一個服務需要知道它所管理的子服務的狀態。
a)NameNode需知道各個Datanode的狀態。
b)JobTracker需知道各個TaskTracker的狀態。
2、心跳檢測機制可通過ZooKeeper來實現。
3、信息推送可由ZooKeeper來實現,ZooKeeper相當于一個發布/訂閱系統。
分布式鎖
處于不同節點上不同的服務,它們可能需要順序地訪問一些資源,這里需要一把分布式的鎖。
分布式鎖具有以下特性:寫鎖、讀鎖、時序鎖。
寫鎖:在zk上創建的一個臨時的無編號的節點。由于是無序編號,在創建時不會自動編號,導致只能客戶端有一個客戶端得到鎖,然后進行寫入。
讀鎖:在zk上創建一個臨時的有編號的節點,這樣即使下次有客戶端加入是同時創建相同的節點時,他也會自動編號,也可以獲得鎖對象,然后對其進行讀取。
時序鎖:在zk上創建的一個臨時的有編號的節點根據編號的大小控制鎖。
分布式隊列
分布式隊列分為兩種:
1、當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達,這種是同步隊列。
a)一個job由多個task組成,只有所有任務完成后,job才運行完成。
b)可為job創建一個/job目錄,然后在該目錄下,為每個完成的task創建一個臨時的Znode,一旦臨時節點數目達到task總數,則表明job運行完成。
2、隊列按照FIFO方式進行入隊和出隊操作,例如實現生產者和消費者模型。
鴻蒙官方戰略合作共建——HarmonyOS技術社區
創建一個Main()線程。
在Main()線程中創建兩個線程,一個負責網絡連接通信(connect),一個負責監聽(listener)。
通過connect線程將注冊的監聽事件發送給Zookeeper。
將注冊的監聽事件添加到Zookeeper的注冊監聽器列表中。
Zookeeper監聽到有數據或路徑發生變化時,把這條消息發送給Listener線程。
Listener線程內部調用process()方法。
首先需要明確zookeeper選舉的規則:leader選舉,要求可用節點數量 > 總節點數量/2。
比如:標記一個寫是否成功是要在超過一半節點發送寫請求成功時才認為有效。同樣,Zookeeper選擇領導者節點也是在超過一半節點同意時才有效。最后,Zookeeper是否正常是要根據是否超過一半的節點正常才算正常。這是基于CAP的一致性原理。
zookeeper有這樣一個特性:集群中只要有過半的機器是正常工作的,那么整個集群對外就是可用的。
也就是說如果有2個zookeeper,那么只要有1個死了zookeeper就不能用了,因為1沒有過半,所以2個zookeeper的死亡容忍度為0;
同理,要是有3個zookeeper,一個死了,還剩下2個正常的,過半了,所以3個zookeeper的容忍度為1;
同理:
2->0;兩個zookeeper,最多0個zookeeper可以不可用。
3->1;三個zookeeper,最多1個zookeeper可以不可用。
4->1;四個zookeeper,最多1個zookeeper可以不可用。
5->2;五個zookeeper,最多2個zookeeper可以不可用。
6->2;兩個zookeeper,最多0個zookeeper可以不可用。
....
會發現一個規律,2n和2n-1的容忍度是一樣的,都是n-1,所以為了更加高效,何必增加那一個不必要的zookeeper呢。
zookeeper的選舉策略也是需要半數以上的節點同意才能當選leader,如果是偶數節點可能導致票數相同的情況。
“Zookeeper面試常見的問題有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。