《面試八股文》之Zookeeper12卷
微信公眾號(hào):moon聊技術(shù)
關(guān)注選擇“ 星標(biāo) ”, 重磅干貨,第一 時(shí)間送達(dá)!
[如果你覺得文章對(duì)你有幫助,歡迎關(guān)注,在看,點(diǎn)贊,轉(zhuǎn)發(fā)]

其他《面試八股文》系列文章請(qǐng)關(guān)注公號(hào)moon聊技術(shù)獲取~
每天一個(gè)知識(shí)點(diǎn)
多想,多思考,多溝通,多交流
目錄
1.Zookeeper 是什么?能做什么?
2.說說 Zookeeper 的數(shù)據(jù)結(jié)構(gòu)吧
3.Znode里面都存儲(chǔ)了什么?
4.Zookeeper 的系統(tǒng)架構(gòu)又是怎么樣的?
5.那你繼續(xù)給我講講 ZAB 協(xié)議吧
6.Zookeeper初始化是如何進(jìn)行Leader選舉的?
7.如果Leader掛了,進(jìn)入崩潰恢復(fù),怎么選舉Leader?
8.說說Wather監(jiān)聽機(jī)制和它的原理?
9.Zookeeper有哪些特性呢?
10.Zookeeper 如何識(shí)別請(qǐng)求的先后順序?
11.選舉 leader 后是怎么進(jìn)行數(shù)據(jù)同步的
12.Zookeeper 會(huì)有數(shù)據(jù)不一致的情況發(fā)生嗎?
1.Zookeeper 是什么?能做什么?
Zookeeper 是一個(gè)開源的,是用于維護(hù)配置信息,命名,提供分布式同步和提供組服務(wù)的集中式服務(wù)。

可以基于 Zookeeper 實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負(fù)載均衡、命名服務(wù)、分布式協(xié)調(diào)/通知、集群管理、Master 選舉、分布式鎖和分布式隊(duì)列等功能。

Zookeeper 最常用的一個(gè)使用場(chǎng)景就是作為注冊(cè)中心,生產(chǎn)者將自己提供的服務(wù)注冊(cè)到 Zookeeper,然后消費(fèi)者從 Zookeeper 中拿到生產(chǎn)者的服務(wù)列表信息,然后再去調(diào)用生產(chǎn)者的內(nèi)容數(shù)據(jù),比如 Dubbo,Kafka 都是使用 Zookeeper 作為注冊(cè)中心的。
2.說說 Zookeeper 的數(shù)據(jù)結(jié)構(gòu)吧

ZooKeeper 提供的名稱空間與標(biāo)準(zhǔn)文件系統(tǒng)的名稱空間非常相似。名稱是由斜杠(“ /”)分隔的一系列路徑元素。ZooKeeper 命名空間中的每個(gè) znode 均由路徑標(biāo)識(shí)。每個(gè) znode 都有一個(gè)父對(duì)象,其路徑是 znode 的前綴,元素少一個(gè);此規(guī)則的例外是 root(“ /”),它沒有父項(xiàng)。此外,與標(biāo)準(zhǔn)文件系統(tǒng)完全一樣,如果 znode 有子節(jié)點(diǎn),則無法刪除它。
ZooKeeper 與標(biāo)準(zhǔn)文件系統(tǒng)之間的主要區(qū)別在于,每個(gè) znode 都可以具有與之關(guān)聯(lián)的數(shù)據(jù)(每個(gè)文件也可以是目錄,反之亦然),并且 znode 限于它們可以擁有的數(shù)據(jù)量。ZooKeeper 旨在存儲(chǔ)協(xié)調(diào)數(shù)據(jù):狀態(tài)信息,配置,位置信息等。這種元信息通常以千字節(jié)(如果不是字節(jié))來度量。ZooKeeper 具有1M的內(nèi)置完整性檢查,以防止將其用作大型數(shù)據(jù)存儲(chǔ),但是通常,它用于存儲(chǔ)小得多的數(shù)據(jù)。

Znode的三種類型:
持久節(jié)點(diǎn)(persistent node)節(jié)點(diǎn)會(huì)被持久 臨時(shí)節(jié)點(diǎn)(ephemeral node),客戶端斷開連接后,ZooKeeper 會(huì)自動(dòng)刪除臨時(shí)節(jié)點(diǎn) 順序節(jié)點(diǎn)(sequential node),每次創(chuàng)建順序節(jié)點(diǎn)時(shí),ZooKeeper 都會(huì)在路徑后面自動(dòng)添加上10位的數(shù)字,從1開始,最大是2147483647 (2^32-1)

Znode的四種形式:
持久節(jié)點(diǎn):如 create /test/a "hello",通過 create 參數(shù)指定為持久節(jié)點(diǎn) 持久順序節(jié)點(diǎn):通過 create -s 參數(shù)指定為順序節(jié)點(diǎn) 臨時(shí)節(jié)點(diǎn):通過 create -e 參數(shù)指定為順序節(jié)點(diǎn) 臨時(shí)順序節(jié)點(diǎn):通過 create -s -e 參數(shù)指定為臨時(shí)及順序節(jié)點(diǎn)
3.Znode里面都存儲(chǔ)了什么?
Znode包含了存儲(chǔ)數(shù)據(jù)(data)、訪問權(quán)限(acl)、子節(jié)點(diǎn)引用(child)、節(jié)點(diǎn)狀態(tài)信息(stat)

data: znode存儲(chǔ)的業(yè)務(wù)數(shù)據(jù)信息 acl: 記錄客戶端對(duì)znode節(jié)點(diǎn)的訪問權(quán)限,如IP等。 child: 當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)引用 stat: 包含Znode節(jié)點(diǎn)的狀態(tài)信息,比如事務(wù)id、版本號(hào)、時(shí)間戳等等。
4.Zookeeper 的系統(tǒng)架構(gòu)又是怎么樣的?

ZooKeeper 分為服務(wù)器端(Server) 和客戶端(Client),客戶端可以連接到整個(gè) ZooKeeper 服務(wù)的任意服務(wù)器上(除非 leaderServes 參數(shù)被顯式設(shè)置,leader 不允許接受客戶端連接),客戶端使用并維護(hù)一個(gè) TCP 連接,通過這個(gè)連接發(fā)送請(qǐng)求、接受響應(yīng)、獲取觀察的事件以及發(fā)送信息。
組成 ZooKeeper 服務(wù)的服務(wù)器必須彼此了解。它們維護(hù)一個(gè)內(nèi)存中的狀態(tài)圖像,以及持久存儲(chǔ)中的事務(wù)日志和快照,只要大多數(shù)服務(wù)器可用,ZooKeeper 服務(wù)就可用;

Zookeeper 集群中Server有三種角色,Leader、Follower 和 Observer
Leader:負(fù)責(zé)投投票的發(fā)起與決議,更新系統(tǒng)狀態(tài),寫數(shù)據(jù) Follower:用于接收客戶端請(qǐng)求并用來返回結(jié)果,在選主過程中參與投票 Observer:可以接受客戶端連接,將寫請(qǐng)求轉(zhuǎn)發(fā)給leader節(jié)點(diǎn),但是不參與投票過程,只同步leader狀態(tài),主要存在目的就是為了提高讀取效率
將 server 分為三種是為了避免太多的從節(jié)點(diǎn)參與過半寫的過程,導(dǎo)致影響性能,這樣 Zookeeper 只要使用一個(gè)幾臺(tái)機(jī)器的小集群就可以實(shí)現(xiàn)高性能了,如果要橫向擴(kuò)展的話,只需要增加 Observer 節(jié)點(diǎn)即可。
Zookeeper 建議集群節(jié)點(diǎn)個(gè)數(shù)為奇數(shù),只要超過一半的機(jī)器能夠正常提供服務(wù),那么整個(gè)集群都是可用的狀態(tài)。
ZooKeeper 啟動(dòng)時(shí),將從實(shí)例中選舉一個(gè) leader,Leader 負(fù)責(zé)處理數(shù)據(jù)更新等操作,一個(gè)更新操作成功的標(biāo)志是當(dāng)且僅當(dāng)大多數(shù) Server 在內(nèi)存中成功修改數(shù)據(jù)。每個(gè) Server 在內(nèi)存中存儲(chǔ)了一份數(shù)據(jù)。
Zookeeper 的數(shù)據(jù)一致性是依靠ZAB協(xié)議完成的。
5.那你繼續(xù)給我講講 ZAB 協(xié)議吧
ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協(xié)議是為 ZooKeeper 特殊設(shè)計(jì)的一種支持崩潰恢復(fù)的原子廣播協(xié)議。在 ZooKeeper 中,主要依賴 ZAB 協(xié)議來實(shí)現(xiàn)分布式數(shù)據(jù)一致性,基于該協(xié)議,ZooKeeper 實(shí)現(xiàn)了一種主備模式的系統(tǒng)架構(gòu)來保持集群中各個(gè)副本之間的數(shù)據(jù)一致性。
ZAB 協(xié)議包括有兩種模式,分別是 崩潰恢復(fù)和消息廣播。
崩潰恢復(fù):當(dāng)整個(gè)服務(wù)框架在啟動(dòng)過程中,或是當(dāng) Leader 服務(wù)器出現(xiàn)網(wǎng)絡(luò)中斷、崩潰退出與重啟等異常情況時(shí),ZAB 協(xié)議就會(huì)進(jìn)人恢復(fù)模式并選舉產(chǎn)生新的 Leader 服務(wù)器。當(dāng)選舉產(chǎn)生了新的 Leader 服務(wù)器,同時(shí)集群中已經(jīng)有過半的機(jī)器與該 Leader 服務(wù)器完成了狀態(tài)同步之后,ZAB 協(xié)議就會(huì)退出恢復(fù)模式。剩下未同步完成的機(jī)器會(huì)繼續(xù)同步,直到同步完成并加入集群后該節(jié)點(diǎn)的服務(wù)才可用。
消息廣播:當(dāng)集群中已經(jīng)有過半的 Follower 服務(wù)器完成了和 Leader 服務(wù)器的狀態(tài)同步,那么整個(gè)服務(wù)框架就可以進(jìn)人消息廣播模式了。當(dāng)一臺(tái)同樣遵守 ZAB 協(xié)議的服務(wù)器啟動(dòng)后加人到集群中時(shí),如果此時(shí)集群中已經(jīng)存在一個(gè) Leader 服務(wù)器在負(fù)責(zé)進(jìn)行消息廣播,那么新加人的服務(wù)器就會(huì)自覺地進(jìn)人數(shù)據(jù)恢復(fù)模式:找到 Leader 所在的服務(wù)器,并與其進(jìn)行數(shù)據(jù)同步,然后一起參與到消息廣播流程中去。ZooKeeper 設(shè)計(jì)成只允許唯一的一個(gè) Leader 服務(wù)器來進(jìn)行事務(wù)請(qǐng)求的處理。Leader 服務(wù)器在接收到客戶端的事務(wù)請(qǐng)求后,會(huì)生成對(duì)應(yīng)的事務(wù)提案并發(fā)起一輪廣播協(xié)議;而如果集群中的其他機(jī)器接收到客戶端的事務(wù)請(qǐng)求,那么這些非 Leader 服務(wù)器會(huì)首先將這個(gè)事務(wù)請(qǐng)求轉(zhuǎn)發(fā)給 Leader 服務(wù)器。
6.Zookeeper初始化是如何進(jìn)行Leader選舉的?

在集群初始化階段,只有兩臺(tái)以以上的 ZK 啟動(dòng)才會(huì)發(fā)生leader選舉,過程如下:
(1) 每個(gè) Server 發(fā)出一個(gè)投票。初始選舉 ZK1 和 ZK2 都會(huì)將自己作為 Leader 服務(wù)器來進(jìn)行投票,每次投票會(huì)包含所推舉的服務(wù)器的(myid, ZXID),此時(shí) ZK1 的投票為(1, 0),ZK2 的投票為(2, 0),然后各自將這個(gè)投票發(fā)給集群中其他機(jī)器。
(2) 收到投票。集群的每個(gè)服務(wù)器收到投票后,首先判斷該投票的有效性,如檢查是否是本輪投票、是否來自 LOOKING 狀態(tài)的服務(wù)器。
(3) 處理投票。每個(gè)發(fā)起投票的服務(wù)器需要將別人的投票和自己的投票進(jìn)行比較,規(guī)則如下:
優(yōu)先檢查 ZXID。ZXID 比較大的服務(wù)器優(yōu)先作為 Leader。如果 ZXID 相同,那么就比較 myid。myid 較大的服務(wù)器作為Leader服務(wù)器。 (4) 統(tǒng)計(jì)投票。每次投票后,服務(wù)器都會(huì)統(tǒng)計(jì)投票信息,判斷是否已經(jīng)有過半機(jī)器接受到相同的投票信息,對(duì)于 ZK1、ZK2 而言,都統(tǒng)計(jì)出集群中已經(jīng)有兩臺(tái)機(jī)器接受了(2, 0)的投票信息,此時(shí)便認(rèn)為已經(jīng)選出 ZK2 作為Leader。
(5) 改變服務(wù)器狀態(tài)。一旦確定了 Leader,每個(gè)服務(wù)器就會(huì)更新自己的狀態(tài),如果是Follower,那么就變更為 FOLLOWING,如果是 Leader,就變更為 LEADING。當(dāng)新的 Zookeeper 節(jié)點(diǎn) ZK3 啟動(dòng)時(shí),發(fā)現(xiàn)已經(jīng)有 Leader 了,不再選舉,直接將直接的狀態(tài)從 LOOKING 改為 FOLLOWING。
7.如果Leader掛了,進(jìn)入崩潰恢復(fù),怎么選舉Leader?

1.變更狀態(tài)。Leader 掛后,余下的非 Observer 服務(wù)器都會(huì)講自己的服務(wù)器狀態(tài)變更為 LOOKING,然后開始進(jìn)入 Leader 選舉過程。
2.每個(gè)非 Observer 的 Server 會(huì)發(fā)出一個(gè)投票。和啟動(dòng)過程一致。
3.接收來自各個(gè)服務(wù)器的投票。與啟動(dòng)時(shí)過程相同。
4.處理投票。與啟動(dòng)時(shí)過程相同。
5.統(tǒng)計(jì)投票。與啟動(dòng)時(shí)過程相同。
6.改變服務(wù)器的狀態(tài)。與啟動(dòng)時(shí)過程相同。
8.說說Wather監(jiān)聽機(jī)制和它的原理?

具體的步驟如下:
服務(wù)注冊(cè):Provider 啟動(dòng)時(shí),會(huì)向 zookeeper 服務(wù)端注冊(cè)服務(wù)信息,也就是創(chuàng)建一個(gè)節(jié)點(diǎn)。 服務(wù)發(fā)現(xiàn):Consumer 啟動(dòng)時(shí),根據(jù)自身配置的依賴服務(wù)信息,向 zookeeper 服務(wù)端獲取注冊(cè)的服務(wù)信息并設(shè)置 watch 監(jiān)聽,獲取到注冊(cè)的服務(wù)信息之后,將服務(wù)提供者的信息緩存在本地,并進(jìn)行服務(wù)的調(diào)用。 服務(wù)通知:一旦服務(wù)提供者因某種原因宕機(jī)不再提供服務(wù)之后,客戶端與 zookeeper 服務(wù)端斷開連接,zookeeper 服務(wù)端上服務(wù)提供者對(duì)應(yīng)服務(wù)節(jié)點(diǎn)會(huì)被刪除,隨后 zookeeper 服務(wù)端會(huì)異步向所有注冊(cè)了該服務(wù),且設(shè)置了 watch 監(jiān)聽的服務(wù)消費(fèi)者發(fā)出節(jié)點(diǎn)被刪除的通知,消費(fèi)者根據(jù)收到的通知拉取最新服務(wù)列表,更新本地緩存的服務(wù)列表。
簡單的理解就是 client 會(huì)對(duì)某個(gè) znode 注冊(cè)一個(gè) watcher 事件,當(dāng)該 znode 發(fā)生變化時(shí),這些 client 會(huì)收到 ZooKeeper 的通知。
四個(gè)特性:
一次性:一旦一個(gè)Wather觸發(fā)之后,Zookeeper就會(huì)將它從存儲(chǔ)中移除,如果還要繼續(xù)監(jiān)聽這個(gè)節(jié)點(diǎn),就需要我們?cè)诳蛻舳说谋O(jiān)聽回調(diào)中,再次對(duì)節(jié)點(diǎn)的監(jiān)聽watch事件設(shè)置為True。否則客戶端只能接收到一次該節(jié)點(diǎn)的變更通知 客戶端串行:客戶端的Wather回調(diào)處理是串行同步的過程,不要因?yàn)橐粋€(gè)Wather的邏輯阻塞整個(gè)客戶端 輕量:Wather通知的單位是WathedEvent,只包含通知狀態(tài)、事件類型和節(jié)點(diǎn)路徑,不包含具體的事件內(nèi)容,具體的時(shí)間內(nèi)容需要客戶端主動(dòng)去重新獲取數(shù)據(jù) 異步: Zookeeper服務(wù)器發(fā)送watcher的通知事件到客戶端是異步的,不能期望能夠監(jiān)控到節(jié)點(diǎn)每次的變化,Zookeeper只能保證最終的一致性,而無法保證強(qiáng)一致性。
9.Zookeeper有哪些特性呢?

順序一致性:leader會(huì)根據(jù)請(qǐng)求順序生成 ZXID 來嚴(yán)格保證請(qǐng)求順序的下發(fā)執(zhí)行。 原子性:所有事務(wù)請(qǐng)求的處理結(jié)果在整個(gè)集群中所有機(jī)器上的應(yīng)用情況是一致的,要么成功,要么就失敗。 單一視圖:無論客戶端連到哪一個(gè) ZooKeeper 服務(wù)器上,看到的數(shù)據(jù)都是一致的。 可靠性:一旦服務(wù)端成功地應(yīng)用了一個(gè)事務(wù),并完成對(duì)客戶端的響應(yīng),那么該事務(wù)所引起的服務(wù)端狀態(tài)變更將會(huì)被一直保留下來。 實(shí)時(shí)性:Zookeeper 僅僅能保證在段時(shí)間內(nèi)客戶端最終一定能夠從服務(wù)端上讀取到最新的數(shù)據(jù)狀態(tài)。
10.Zookeeper 如何識(shí)別請(qǐng)求的先后順序?

Leader 收到請(qǐng)求之后,會(huì)將每個(gè)請(qǐng)求分配一個(gè)全局唯一遞增的事務(wù)ID:zxid,然后把請(qǐng)求放入到一個(gè) FIFO 的隊(duì)列中,之后就會(huì)按照 FIFO 的策略發(fā)送給所有的 Follower。
11.選舉 leader 后是怎么進(jìn)行數(shù)據(jù)同步的

前面提到寫數(shù)據(jù)是由 leader 負(fù)責(zé)的,而 leader 會(huì)將每個(gè)請(qǐng)求分配一個(gè) ZXID,放入一個(gè)隊(duì)列中,依次執(zhí)行,每次 leader 執(zhí)行完一個(gè)請(qǐng)求后,會(huì)記錄下執(zhí)行的這個(gè) ZXID。
我們將這個(gè)隊(duì)列中最大的 ZXID 稱為 maxZXID,最小的 ZXID 稱為 minZXID。
將 Observer 和 follower 中最新的 ZXID 稱為lastSyncZXID
proposal : l其實(shí)就是將請(qǐng)求中的一些信息如請(qǐng)求頭,請(qǐng)求體以及 ZXID 等信息封裝到 proposal對(duì)象當(dāng)中
1.差異化同步
1).leader 向 Observer 和 follower 發(fā)送 DIFF 指令,之后就開始差異化同步 2).然后把差異數(shù)據(jù) 提議 proposal 發(fā)送給 Observer 和 follower , Observer 和 follower 返回ACK表示已經(jīng)完成了同步 3).只要集群中過半的 Observer 和 follower 響應(yīng)了 ACK 就發(fā)送一個(gè) UPTODATE 命令 4).leader 返回 ACK,同步流程結(jié)束 觸發(fā)條件:minZXID < lastSyncZXID < maxZXID
同步過程:
2.回滾同步
1).直接回滾到 maxZXID 觸發(fā)條件 maxZXID < lastSyncZXID 舉個(gè)例子:a,b,c三臺(tái)服務(wù)服務(wù)器 a是leader,此時(shí)隊(duì)列里面最大的 ZXID 為100,a 收到請(qǐng)求,該 ZXID 為101,還沒來得及發(fā)送同步數(shù)據(jù) a 就掛了,b 變?yōu)閘eader,然后 a 恢復(fù)了,此時(shí)就需要 a 先將之前 ZXID 為101的數(shù)據(jù)回滾 同步過程: 3.回滾+差異化同步
1).Observer 和 follower 將數(shù)據(jù)回滾 2).進(jìn)行差異化同步 觸發(fā)條件:如果Leader剛生成一個(gè)proposal,還沒有來得及發(fā)送出去,此時(shí)Leader宕機(jī),重新選舉之后作為Follower,但是新的Leader沒有這個(gè)proposal數(shù)據(jù) 舉個(gè)例子:a,b,c三臺(tái)服務(wù)服務(wù)器 a是leader,此時(shí)隊(duì)列里面最大的 ZXID 為100,a 收到請(qǐng)求,該 ZXID 為101,還沒來得及發(fā)送同步數(shù)據(jù) a 就掛了,b 變?yōu)閘eader,b 又處理了3個(gè)請(qǐng)求,則 b 隊(duì)列中最大的 ZXID 為103,然后 a 恢復(fù)了,此時(shí)就需要 a 先將之前 ZXID 為101的數(shù)據(jù)回滾,再進(jìn)行同步 同步過程: 4.全量同步
1).lastSyncZXID < minZXID 2).Leader服務(wù)器上沒有緩存隊(duì)列,并且lastSyncZXID!=maxZXID 觸發(fā)條件 同步過程:leader 向 Observer 和 follower 發(fā)送SNAP命令,進(jìn)行數(shù)據(jù)全量同步
12.Zookeeper 會(huì)有數(shù)據(jù)不一致的情況發(fā)生嗎?
還是會(huì)有的,因?yàn)?Zookeeper 采用的是過半寫機(jī)制,意味著3臺(tái)服務(wù)器只要有兩臺(tái)寫成功就代表整個(gè)集群寫成功,如果剛好有請(qǐng)求打在這臺(tái)還未寫的服務(wù)器上就查詢不到該數(shù)據(jù),就會(huì)有數(shù)據(jù)不一致的情況產(chǎn)生。
往期推薦
確定不勾搭一下moon嗎?
玩玩技術(shù),聊聊人生,看看生活,搞搞理想!
一起來吐槽職場(chǎng)吧~
