概述
? ? 本文的主要目的是分析zookeeper的整個數(shù)據(jù)寫入過程,相信大家或多或少都聽說過zookeeper是一個集中式的單點寫入過程,所有的寫入請求都會轉(zhuǎn)發(fā)到Leader來完成數(shù)據(jù)的寫入過程,而且在整個寫入過程當中會涉及到二次提交(proposal/commit)過程,希望通過這篇文章能夠幫助感興趣的人建立一個整體的流程印象。
? ? 延伸閱讀關(guān)于Paxos的協(xié)議可以閱讀延伸的文章《拜占庭將軍問題》,其實zookeeper的二階段提交就是這個模型的實現(xiàn),公式證明看不懂但是思路可以看得懂。
? ? 最后整個文章讀起來比較費力,如果有興趣真正搞懂整個寫入過程,還是需要抽出一整塊時間來閱讀的,我本人這篇文章從理清楚過程到畫圖大概花了一個星期左右,這還是建議閱讀別人的文章的基礎(chǔ)上的,參考文章中列出的幾篇文章還是非常不錯的,可以相互補充著來看,因為整個過程涉及的代碼太多了,所以就建議大家看參考文獻中的文章吧,雖然有一些小出入但是整體來說是非常全面的。
? ? zookeeper中涉及的事務(wù)操作主要包括下面幾大類:
????????1)寫操作(OpCode.create,OpCode.delete,OpCode.setData,OpCode.setACL)
????????2)Session的創(chuàng)建和關(guān)閉操作(OpCode.createSession和OpCode.closeSession)
????????3)OpCode.multi操作。
過程分析
? ? 在正式進入過程分析之前,先得有一個宏觀的印象,那就是zookeeper的寫入過程當中,當我們連接的是Follower的對象的時候,寫入會轉(zhuǎn)發(fā)到Leader,最后由Leader完成寫入并同步到所有Follower當中,F(xiàn)ollower是不具備處理數(shù)據(jù)寫入功能,F(xiàn)ollower其實只是對寫入的一個轉(zhuǎn)發(fā)而已,從下面這個圖片就可以看明白了。

? ? 另外,在zookeeper的FollowerZookeeperServer和LeaderZookeeperServer當中,都有一個調(diào)用鏈的概念,在接收報文后會通過調(diào)用鏈進行處理后回送報文,其中l(wèi)eader端和Follower端的調(diào)用鏈是有區(qū)別的,具體差別就是下圖的樣子。


????在整個交互過程中比較核心的兩類報文,Request對象是調(diào)用鏈處理過程中傳輸?shù)膶ο?,QuoromPacket是follower和leader交互過程涉及的報文。


整個核心的數(shù)據(jù)寫入過程都在下面這個圖當中,核心的關(guān)注點要關(guān)注幾個角色之間交互報文以及兩階段提交過程。

下面過程分析的數(shù)字編號不是對應(yīng)上圖當中的編號,而是宏觀上按順序把整個過程進行分解,當然每個過程都是可以在上圖中找到對應(yīng)的連接線的(源碼層面可以看ZooKeeper源碼分析:Quorum請求的整個流程)。
????1、client向follower發(fā)送packet報文,然后進入follower的消息處理鏈當中,也就是FollowerRequestProcessor當中。
????2、Follower的處理過程:FollowerRequestProcessor做兩個事情:負責沿著調(diào)用鏈處理也就是執(zhí)行CommitProcessor當中,在這個時候follower的處理就暫時停留在了CommitProcessor當中;負責將報文通過follower.request()發(fā)送到leader當中,此時報文的type為Leader.REQUEST。
????3、Leader的處理過程:Leader端由LearnerHandler(負責和follower建立的連接)進行處理,核心處理邏輯其實就兩個:邏輯一依次通過調(diào)用鏈PrepRequestProcessor ->?ProposalRequestProcessor->SyncRequestProcessor(CommitProcessor),其中CommitProcessor其實處理到一半沒有繼續(xù)往下執(zhí)行;邏輯二是PrepRequestProcessor ->?ProposalRequestProcessor->發(fā)送Leader.PROPOSAL報文給Follower。
????4、Follower的處理過程:Follower在接收到Leader的Proposal報文以后,通過調(diào)用鏈SyncRequestsProcessor->SendAckRequestProcessor發(fā)送Leader.ACK報文給Leader。
????5、Leader的處理過程:Leader在收到Follower的ack報文以后,會判斷是否超過半數(shù)已經(jīng)回復(fù)了相應(yīng)報文,也就是對應(yīng)的tryToCommit的處理邏輯,里面其實就是判斷是否超過半數(shù)的follower回復(fù)了,如果超過半數(shù)回復(fù)了那么就進入了第二個階段(Commit/Inform)階段發(fā)送給Follower,當然leader本身會在之前的CommitProcessor當中繼續(xù)操作(也就是在步驟3當中執(zhí)行到一半的過程),沿著調(diào)用調(diào)用CommitProcessor->ToBeAppliedRequestProcessor->FinalRequestProcessor完成數(shù)據(jù)的寫入。
????6、Follower收到Leader.COMMIT/INFORM報文之后開始進行數(shù)據(jù)的持久化,并將響應(yīng)報文發(fā)送給client,整個過程就結(jié)束了。
參考文章
????ZooKeeper學(xué)習(xí)之server端實現(xiàn)的基本骨架