導航:首頁 > 源碼編譯 > zookeeper的底層源碼

zookeeper的底層源碼

發布時間:2023-02-19 00:20:38

❶ zk源碼閱讀37:ZooKeeperServer源碼分析

前面針對server啟動到選舉leader進行了一個小結,現在進入leader和follower的啟動交互過程,需要先講ZooKeeperServer,
在之前源碼閱讀的25節裡面帶過了一部分,這里詳細講解ZooKeeperServer的源碼

繼承關系如下

本節主要講解內容如下

在源碼閱讀第24節講解了,這里不贅述

是SessionTracker的內部介面

如下圖

除去log,jmx相關部分,源碼如下

ChangeRecord是ZooKeeperServer的內部類,下面會介紹
ServerStats,ZooKeeperServerListener都在25節的源碼介紹過

這個類並沒有調用,不用管

定義異常

這個數據結構為了促進PrepRequestProcessor以及FinalRequestProcessor的信息共享,講到調用鏈的時候再講。

其中,StatPersisted在源碼閱讀7中講DataNode的時候講過了

描述當前server所處的狀態

這里列舉處兩個底層調用的構造函數

啟動涉及到db的數據載入,這里也有集群和單機兩種,調用順序為

主要是集群的時候,server選完了leader,由leader才能調用數據載入loadData

下面按照單機版startdata函數展開

初始化zkDb完成數據載入

恢復session和數據,單機版啟動或者集群版leader選舉之後調用lead方法時,會調用該方法。
主要完成設置zxid以及把無效的session給kill掉的工作

這里注意,為什麼需要干這件事情,在下面思考中會說

裡面調用了setZxid(不展開)以及killSession函數

清除db中臨時會話記錄,會話跟蹤器也清除記錄

入口是ZooKeeperServer#startup,zkServer都是在上述載入了db的數據之後,調用startup來完成啟動

啟動的入口函數

調用了createSessionTracker等函數,介紹如下

createSessionTracker 完成會話跟蹤器的創建

這里是默認的單機版實現,在集群版不同的角色有不同的實現,主要是參數sid不會傳1,而是配置中的sid

startSessionTracker 啟動會話跟蹤器

設置伺服器運行狀態,對於ERROR和SHUTDOWN的state,進行對應的操作

源碼閱讀25:伺服器異常報警,關閉機制 講過,這里不贅述

安裝請求處理鏈路,是PrepRequestProcessor -> SyncRequestProcessor -> FinalRequestProcessor順序
具體在後面請求處理鏈路再講

兩個函數getServerId和expire

processConnectRequest用於處理client的連接請求,不展開
值得注意的地方是重連的調用

展開如下

重連的核心函數

驗證sessionId和傳遞來的密碼的正確性

根據sessionId生成密碼

在會話跟蹤器SessionTracker中判斷會話是否還有小

完成會話初始化,根據參數valid代表認證通過與否,用來判斷server是接收連接請求,還是發出closeConn的請求,不展開,重要部分如下

除去的get,set,jmx,shutdown相關函數,剩下重要函數如下

部分函數列舉如下

獲取下一個server的zxid,調用方需要確保控制並發順序

上面ZooKeeperServer#expire調用了close函數,介紹如下
該函數用於提交一個 關閉某個sessionId 的請求

這里有兩個函數

之前在源碼21節 會話管理中講解了會話清除,在sessionTracker的記錄是馬上清除的,而DateTree中臨時會話的清除是通過調用鏈一步步來的,也就是說兩個步驟不是同步的,所以如果中間伺服器狀態改變了,會出現不一致的情況

requestsInProcess代表正在處理的請求個數

就是說發出請求時,requestsInProcess+1,最後完成請求時,requestsInProcess-1.涉及到請求處理鏈。

ZooKeeperServer#checkPasswd調用
ZooKeeperServer#generatePasswd

就是sessionId要和sessionId^superSecret生成的第一個隨機數相匹配即可
密碼不是client端設置的,是根據sessionId生成的

ZooKeeperServer#processConnectRequest 裡面調用reopenSession中
在上面已經講了,核心就是

這里還沒有深入看,先存疑

比如思考中提到的loadData為什麼會出現數據不一致,屬於某種異常情況的處理

為什麼不放到另外一個類裡面去

❷ Zookeeper之兩階段提交源碼分析

zookeeper集群為了保證數據一致性,使用了兩階段提交。
在zookeeper集群的角色有:leader、follower、observer。
在這幾個角色中處理讀寫請求是不同的:
讀請求:從當前節點直接讀取數據
寫請求:在leader直接進行兩階段提交、在非leader則是把請求轉交給leader處理
所以,分析兩階段提交就是分析集群模式下的請求處理。在單機模式在請求處理是經過RequestProcessor請求處理鏈處理。
單個zookeeprt請求處理主要有以下幾步:
1、對當前請求生成日誌txn
2、持久化日誌txn
3、根據日誌txn更新Database
兩階段提交(2PC)步驟:

其中標綠色的PrepRequestProcessor、SyncRequestProcessor、CommitProcessor都繼承了ZooKeeperCriticalThread是一個線程。
org.apache.zookeeper.server.quorum.LeaderZooKeeperServer#setupRequestProcessors

org.apache.zookeeper.server.quorum.ProposalRequestProcessor#ProposalRequestProcessor

org.apache.zookeeper.server.quorum.LeaderRequestProcessor#processRequest

①、檢查是不是local session本地session,創建臨時節點會升級session
org.apache.zookeeper.server.quorum.QuorumZooKeeperServer#checkUpgradeSession

②、交給下一個請求處理器處理

作用與單機模式相同,給請求Request的Hdr和Txn賦值,然後交給下一個請求處理器處理

如果是寫請求(request.getHdr() != null),則會把當前請求封裝為協議並發送給follower。發送之後交給SyncRequestProcessor持久化處理

org.apache.zookeeper.server.quorum.Leader#propose

org.apache.zookeeper.server.quorum.Leader#sendPacket
發送到所有其他Followe節點forwardingFollowers

把請求放入到queuedRequests阻塞隊列

①、對請求進行持久化與單機相同
org.apache.zookeeper.server.SyncRequestProcessor#run

向lead發送自己的ack(2PC發送ACK)

org.apache.zookeeper.server.quorum.Leader#processAck

org.apache.zookeeper.server.quorum.Leader#tryToCommit

org.apache.zookeeper.server.quorum.CommitProcessor#commit
提交當前請求,放入到committedRequests,最終會更新database

CommitProcessor類參數:
queuedRequests:表示接收到的請求,沒有進行兩階段的提交
queuedWriteRequests:表示接收到的寫請求,沒有進行兩階段的提交
committedRequests:表示可以提交的請求,在兩階段驗證過半之後進行會在本地進行committe操作,便添加到這個隊列
commitIsWaiting:表示存在可以提交的請求(committedRequests是否有值,有true)
pendingRequests:是一個map集合,表示每個客戶端sessionId的請求
Leader類參數:
outstandingProposals:表示記錄提議的請求的隊列,符合過半機制之後會移除
toBeApplied:表示記錄待生效的請求,在FinalRequestProcessor移除
①、processRequest
org.apache.zookeeper.server.quorum.CommitProcessor#processRequest

首先判斷是否需要兩階段提交。如果需要則會添加到queuedWriteRequests隊列
org.apache.zookeeper.server.quorum.CommitProcessor#needCommit
如果是更改操作則返回true

d、然後,再看一下這個while的退出條件。
①、從queuedRequests取出的是空
②、如果queuedRequests數據不為空,那麼requestsToProcess是大於0的。這時只有maxReadBatchSize < 0或readsProcessed <= maxReadBatchSize才能退出。
maxReadBatchSize < 0表示默認是-1,如果配置了這個參數當連續讀了readsProcessed時,也會退出。
③、pendingRequests和committedRequests不為空
e、commitIsWaiting有待提交的

org.apache.zookeeper.server.quorum.Leader.ToBeAppliedRequestProcessor#processRequest
刪除toBeApplied

其中標綠色的FollowerRequestProcessor、CommitProcessor、SyncRequestProcessor都繼承了ZooKeeperCriticalThread是一個線程。
org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#setupRequestProcessors

開了兩條鏈:
FollowerRequestProcessor(firstProcessor)---->CommitProcessor----->FinalRequestProcessor
SyncRequestProcessor---->SendAckRequestProcessor

org.apache.zookeeper.server.quorum.FollowerRequestProcessor#processRequest
請求添加到queuedRequests隊列

FollowerRequestProcessor是一個線程,會從queuedRequests獲取請求
org.apache.zookeeper.server.quorum.FollowerRequestProcessor#run

createSession和closeSession也會轉發給lead節點處理

org.apache.zookeeper.server.quorum.SendAckRequestProcessor#processRequest
在用SendAckRequestProcessor處理之前會先調用SyncRequestProcessor進行持久化處理,由於與單機或lead處理相同就不單獨列出來了。
向領導者發送確認ack包

org.apache.zookeeper.server.quorum.Learner#writePacket

在經過FollowerRequestProcessor處理後,lead端會得到一個Request的請求
org.apache.zookeeper.server.quorum.LearnerHandler#run

org.apache.zookeeper.server.quorum.Leader#submitLearnerRequest

在連接Follower節點的客戶端發送更改命令請求會轉發到leader節點的prepRequestProcessor進行處理

1、run
org.apache.zookeeper.server.quorum.QuorumPeer#run

2、followLeader
org.apache.zookeeper.server.quorum.Follower#followLeader
不斷讀取從lead端的數據包

org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#logRequest

其中標綠色的ObserverRequestProcessor、CommitProcessor、SyncRequestProcessor都繼承了ZooKeeperCriticalThread是一個線程。
org.apache.zookeeper.server.quorum.ObserverZooKeeperServer#setupRequestProcessors

也是開了兩條鏈:
ObserverRequestProcessor(firstProcessor)---->CommitProcessor----->FinalRequestProcessor
SyncRequestProcessor---->null
observer節點不參與兩階段提交,所以同步SyncRequestProcessor之後沒有ACK確認提交。這樣既提高了讀效率,又對寫效率沒有影響。請求處理鏈與leader、follower的功能相同不再累述。

zookeeper集群的兩階段提交,是在寫操作的情況下發生的。2PC的整體實現邏輯是在RequestProcessor請求處理鏈處理的。只有在接受到的ACK超過一半才會進行提交,提交的實現邏輯是在CommitProcessor中實現的,CommitProcessor處理器中裡面涉及多種集合、隊列等參數(需要首先了解這些參數意義,然後再讀CommitProcessor源碼)。

❸ Zookeeper選主過程,理論和源碼結合,看這一篇足夠了

【共4239字,閱讀需要15分鍾】

Zookeeper作為Dubbo生態的默認注冊中心,得到了非常的普遍的應用,雖然後來阿里又出了nacos,但是不可否認的是ZK仍然是一款非常優秀的開源產品,非常優秀的注冊中心備選方案。

ZK有很多特性,本篇文章主要介紹ZK的選主過程(後宮佳麗三千,我就獨寵你一人)

要說選主的過程,我們首先得了解ZK到底有哪些節點,這些節點充當得角色是什麼?

ZK本身得節點主要分為三類:

Leader:主要是負責數據的寫入,如果超過半數同意,那麼就廣播進行寫入;

Follower:主要負責查詢請求並將寫入請求發送給leader,參與選舉和寫入投票;

Observe:也是負責查詢請求並將寫入請求發送給leader,不參加投票,只被動接收結果

獲取半數投票以上的節點成為leader節點。

萬事萬物都有一個准則,好的比較壞的,壞的比較更壞的,世上本沒有痛苦,痛苦都是自己尋找的結果,海燕你可長點心吧,哎呀跑偏了。

ZK比較的時候有三個指標或者三個維度:

(1)任期

(2)事務ID(ZK中的事務ID)

(3)節點編號(集群中每個節點的編號)

根據以上三個指標就可以說出最終的結論了:選擇任期大的,任期一樣選擇事務ID大的,前兩個都一樣,選擇節點編號大的。

就這么簡單?是的。規則就是這么簡單,但是源碼還是有那麼一丟丟的繞。

源碼看著相對比較枯燥,但是作為一個手藝人,怎麼能不去了解怎麼做的呢,我們先來梳理一下代碼的流程,方便更好的看第四部分內容。

節點先投自己一票,然後進行廣播

節點內部循環進行消息接收

收到消息後

如果消息為空,就進行重新發送消息或者建立連接

如果消息不為空,且消息接收者和投票的leader都是合法節點就進行下邊步驟。

如果節點為looking節點

根據當前節點的投票和接收到的投票進行比較來決定是否需要再次發送投票並且記錄投票的結果

每次都判斷記錄的票數,如果過半就進行節點狀態的設置

選主的邏輯是在lookForLeader開始的,像金字塔的第一塊磚一樣,我們先看ZK選主的第一塊磚lookForLeader,第一次看源碼得時候一定要把握主線,忽略從線,等主線完全理清楚了之後才去處理從線,要不會陷入迷宮之中。

下邊就是主要的投票代碼,看里邊的注釋:

更新投票或者投票的方法為:

發送通知的方法為:

待到山花爛漫時,她在叢中笑,消息都已經發完了,肯定就到了接收到選票的時候應該怎麼操作了,接收選票的代碼也是在lookForLeader中:

接上代碼繼續討論,校驗發送投票節點的狀態,我們從本文的第一章節知道Observe節點是不參與投票的,只是轉發寫請求和被動接收數據,負責查詢請求,所以從代碼中我們也可以看出來:

當發送投票的節點狀態是FOLLOWING和LEADING時,代表發送節點已經選舉完成,所以處理方法的邏輯都是一樣滴,這部分限於篇幅太長,暫時就不深入討論了,感興趣的朋友可以私信我或者加我微信號M_P_E_D進行交流和溝通。

終於到重頭戲了,咱們看看LOOKING狀態時的代碼:
我們先把totalOrderPredicate方法放前邊,這個其實就是選舉leader的規則的實現。

道阻且長,行則將至,行而不輟,未來可期,加油。

閱讀全文

與zookeeper的底層源碼相關的資料

熱點內容
php正則class 瀏覽:732
怎麼在文件夾查找一堆文件 瀏覽:541
核酸報告用什麼app 瀏覽:789
u8怎麼ping通伺服器地址 瀏覽:992
安卓什麼手機支持背部輕敲調出健康碼 瀏覽:868
程序員抽獎排行 瀏覽:742
扭蛋人生安卓如何下載 瀏覽:722
什麼app文檔資源多好 瀏覽:922
黑馬程序員APP 瀏覽:146
掌閱小說是哪個app 瀏覽:45
如何把u盤的軟體安裝到安卓機 瀏覽:998
php跑在什麼伺服器 瀏覽:122
編譯器怎麼跳轉到下一行 瀏覽:450
嵌入式py編譯器 瀏覽:324
rplayer下載安卓哪個文件夾 瀏覽:298
安卓手機里的電子狗怎麼用 瀏覽:748
pythonspyder入門 瀏覽:764
趣質貓app是什麼 瀏覽:61
皮帶壓縮機經常吸不上 瀏覽:206
西部隨行版怎樣加密 瀏覽:996