問題
帶着問題擼源碼系列-zookeeper-客戶端發寫請求,最終怎麼通過2PC同步到集羣所有機器?
猜測
we all know the 2PC, but how exactly does it work?
理論上,就是leader接收到請求,然後發給Prepare,讓小夥伴們準備好,過半數人回覆ok了之後,leader回覆客戶端,然後再發Commit請求讓小夥伴們真正提交
源碼
Follower接收到客戶端的寫請求,會先根據責任鏈調下一個Processor,然後把寫請求轉發給Leader。
leader接收到轉發的寫請求,然後會怎麼樣?那就得研究Leader的責任鏈了。。
所以我們先找Leader的責任鏈:
org.apache.zookeeper.server.quorum.LeaderZooKeeperServer
上來文件頭部的註釋就有相關的說明了:
/**
*
* Just like the standard ZooKeeperServer. We just replace the request
* processors: PrepRequestProcessor -> ProposalRequestProcessor ->
* CommitProcessor -> Leader.ToBeAppliedRequestProcessor ->
* FinalRequestProcessor
*/
PrepRequestProcessor -> ProposalRequestProcessor -> CommitProcessor -> Leader.ToBeAppliedRequestProcessor -> FinalRequestProcessor
所以我們可以從PrepRequestProcessor
開始看了:
不斷地從submittedRequests
中取Request。最後調用pRequest(request)
,來到下一個Processor,斷點打起來~
ProposalRequest
走else邏輯直接調用了nextProcessor
那就到CommitProcessor
因爲是寫請求,走if分支,QueuedWriteRequest
隊列中加入了請求。
然後找消費這個隊列的地方:
這裏查了一下消費到的是不是本地的寫請求。
注:如果是本地的寫請求,說明是leader直接接收到寫請求。我們認爲沒走這個分支。(在這打個斷點,理論上不應該走到這)
斷點調試
server1、2、3順序啓動,server2是leader,debug方式啓動server2
client連到server2,直接給leader發請求 create /t2
!!!!!!!這裏要特別注意,在調試的過程中我們啓動的server2本來是leader的,調試經常導致斷線,斷線之後server2就不是leader了,得特別注意!
爲了避免這種情況,我們把server3幹掉;這樣,如果server2超時,只剩下server1,無法對外提供服務;server2活過來的話仍然是leader
先來到PrepRequestProcessor
責任鏈到下一個Processor
來到ProposalRequestProcessor
調用責任鏈下一個Processor,來到CommitProcessor
請求加入到pendingRequests
來到Leader,發送Propose請求
點收選票,這時候收到了來自與自己和server1的ack
然後來到了leader的commit
再從pendingRequest中取出了我們的請求
最後來到FinalRequestProcessor,寫入硬盤
回答問題
理論是正確的!後面再細化一下流程