zookeeper源碼學習(一)

最近在學習paxos和zookeeper,有收穫也有很多不懂的地方,寫些筆記,希望和對paxos感興趣的同學一起討論哈,不懂的問題還希望能得到大牛們的指點~~呵呵

學習過程中,受教於多位前輩的文章:

淘寶核心技術團隊 : http://rdc.taobao.com/blog/cs/?p=162

CODEDUMP博客 : http://www.codedump.info/?p=224

xhh198781的專欄 : http://blog.csdn.net/xhh198781/article/details/6619203

 

Zookeeper的一致性的實現分爲兩個部分:leader選舉,數據同步。

 

zookeeper集羣的運行過程:

Zookeeper集羣的基本運行過程是,server啓動時首先從配置文件中讀取數據,之後各個server發送自己的投票進行選舉,選出leader之後,各個server接收/監聽客戶端請求,leader與followers同步數據,當數據同步完成後就可以回覆客戶端的請求。讀請求可以由接受請求的server直接回復,寫請求要發送到leader進行處理。當leader宕機時。Follower發現leader失效則發起新一輪的選舉(是發現leader失效便進行選舉還是租約超時時進行選舉?),選出新的leader後,leader與followers同步數據……如此進行

 

zookeeper集羣主要數據的含義:

Server啓動時從磁盤中讀取的數據:

Id  :server id,這個id唯一標識一臺機器,存儲在myid文件中,配置集羣時手動寫入

Zxid:標識了本機想要選舉誰爲leader,是本機目前所見到的最大的id值(在代碼裏面這個zxid是怎麼增長的?)

投票時發送的消息包括四種信息:

Id    :server id,這個id唯一標識一臺機器,存儲在myid文件中,配置集羣時手動寫入

Zxid  :標識了本機想要選舉誰爲leader,是本機目前所見到的最大的id值

epoch:標識leader的變更,表示每個算法instance的一個round

state :本機的狀態信息(包括looking,leading,following,observing)

 

zookeeper集羣的leader選舉:

Zookeeper用於選舉leader有三個類:FastLeaderElection類,LeaderElection類,AuthFastLeaderElection類。默認使用FastLeaderElection類。FastLeaderElection選舉算法用到的類是FastLeaderElection類,在org.apache.zookeeper.server.quorum包中。

 

FastLeaderElection類的主要屬性成員:

FinalizeWait:這是一個server得知他完成/贏得了選舉後需要等待的時間。在zookeeper中,只有收到了所有server的回覆並且由這些回覆信息可以選出leader,那麼選舉過程可以結束。如果僅收到了一個多數派的回覆,即使這個多數派選出了一個leader,也要等待一段時間即FinalizeWait,如果在這段時間內沒有新消息到來纔可以確定選舉結束。這麼做是爲了保證不會有哪個server因爲啓動較晚(在其他server完成了選舉之後才啓動)或者其他原因沒有參與到選舉中來而導致id更大的server沒有成爲leader。

MaxNotificationInterval:兩個連續的通知檢查之間的時間上限,默認60秒,它是指數退避算法的界限值(這個應該是paxoslease中用到的)

QuorumCnxManager對象manager:管理TCP連接,FastLeaderElection消息是使用TCP數據報的。

linkedBlockingQueue<ToSend> sendqueue : 存儲tosend消息,本server要向其他server發送的消息

linkedBlockingQueue<Notification> recvqueue :存儲notification消息,本server從其他server接收到的回覆消息。這個消息隊列是本地消息隊列,經過WorkerReceiver線程處理後發過來的。不同於recvQueue隊列,該隊列是外部消息隊列,接受所有外部發來的消息。

WorkerSender ws:發送消息線程類的對象,作爲後臺線程運行(Daemon)

WorkerReceiver wr:接收消息線程類的對象,作爲後臺線程運行(Daemon)

QuorumPeer self:

Logicalclock:我的理解是標識一個實例中的一個round

ProposedLeader:選舉的leader的id

ProposedZxid:選舉的leader的zxid      (這兩個數據算作是持久化的數據吧?)

 

該類中主要的內部類:

1.表示數據結構的類:

Notification類:消息結構,當本server改變了所選舉的leader時向其他server發送消息用的數據結構。該類包括了5個主要數據:

   Leader – 本server想要選舉的leader的id(server id)

   Zxid  -- 本server想要選舉的leader的zxid

   Epoch – 標識算法instance中的一個round

   State – 本server的當前狀態(包括looking,leading,following,observing)

   Sid  – 發送方server的ip地址

ToSend類:消息結構,server傳遞消息的數據結構

   Leader – 本server想要選舉的leader的id(server id)

   Zxid  -- 本server想要選舉的leader的zxid

   Epoch – 標識算法instance中的一個round

   State – 本server的當前狀態(包括looking,leading,following,observing)

   Sid  – 接收方server的ip地址

2.線程池Messenger類

Messenger類中有兩種線程:

   WorkerReceiver線程類:接收線程,接收來自其他server的消息並處理這些消息,在選舉過程沒有停止的時候,接收線程就循環處理接收到的消息。處理消息的過程是:在外部消息隊列recvQueue中取得一個消息,如果這個消息的發送端是個observer,那麼立刻回覆,將本server要選舉的leader、當前狀態、epoch信息發送過去。如果這個消息來自於一個participate,那麼按本server的狀態討論,如果本server處於looking狀態,那麼將該消息放到本地接收隊列中,同時判斷髮送方的狀態,如果發送方也是looking狀態並且其epoch值比較小,那麼回覆它一個消息告知本server的選舉的leader信息。如果本server不是looking狀態,而對方是looking狀態的話,就回復一個消息告知本server所知道的leader信息。

WorkerSender線程類:發送線程,負責發送消息到其他server。發送消息的過程是:只要選舉沒有停止就從本地發送隊列sendqueue中取一個消息並將它發送到指定的server。

 

發送線程:

逐個將sendqueue隊列中的消息發出去。

 

接收線程:

在選舉過程沒有停止時,循環處理隊列中的消息。

如果消息來自observer,立即回覆,相應代碼段:

zookeeper源碼學習(一)

如果消息來自另一個participate,進行判斷:

若本server是looking狀態,則將該消息放入到本地隊列recvqueue中以備lookForLeader()方法使用。如果同時對方也是looking狀態並且提案號比本server小,則回覆一個消息告知本server選舉的leader等信息。(如果本server和對方都是looking狀態,但對方的提案號比本server的提案號大,這種情況會在選舉線程中做處理,此時該消息已經放入了本地消息隊列)。對應代碼段:

zookeeper源碼學習(一)

若本server不是looking狀態(leading狀態或者following狀態),對方是looking狀態,則向它告知本節點目前所知的leader信息。(這種情況很可能是應爲一個多數派已經通過一個leader,選舉完成,但是由於一些原因有些server還不知道選舉已經完成了,在選舉線程lookforLeader()方法中的最有一個case語句處理的就是這種情況)。對應的代碼段:

zookeeper源碼學習(一)

 

選舉線程:

選舉由LookForLeader ()方法完成。

兩個局部變量:

Hashmap  recvset -- 用來存儲本輪選舉中從participate server接收到的合法消息。每當有更高編號的提案被髮起時,recvset都被清空(舊消息是上一輪選舉的信息,新輪開始時它們已經沒有用了)。

Hashmap  outofelection -- (這個不理解哎)

選舉過程:

1.

【我不是很理解zookeeper是怎麼用的fast paxos,leader選舉是沒有leader要選leader,而fast paxos是需要leader在開始的階段發送一個any message的。我的理解是這一步是fast paxos中省略了prepare階段後直接執行的P2(a)段,將本server所選的值和提案號一併發給所有其他的participate server。這是站在proposer角度所做的動作  提案】

因爲該線程是發起選舉的線程,所以首先增加logicalclock(算法的提案編號),表示進入了下一輪選舉。同時初始化/更新提案信息:本serverid和目前本server看到的最大的zxid。用這個兩個數據來初始化/更新提案信息,集羣啓動時zxid都是0,各個server都選舉自己做leader。向所有participate server發送這個提案消息(以Notifications消息的形式,因爲此時leader改變了)。

對應的代碼段:

zookeeper源碼學習(一)

2.選舉沒有結束時,循環處理本地消息隊列recvqueue中的消息

如果本地消息隊列recvqueue中已經沒有消息,那麼檢查queueSendMap隊列,如果其中沒有消息,則重新向所有的participate server發送notification消息;如果其中還有未發送的消息,則這些剩餘消息的目的server重新建立連接,並將消息發送給它們。使用指數退避算法更改notTimeout值,notTimeout是在消息隊列中取消息沒有取到時,距下次取所間隔/等待的時間。對應的代碼段:

zookeeper源碼學習(一)

 

如果本地消息隊列中有消息,則取出下一個消息,並按其發送端server的狀態來處理:

1)發送端server是looking狀態

  【這個地方我覺得是進行的P2(b)階段,針對號和值的大小分別對其他participate的回覆/提案消息進行處理。該是站在accepter角度的動作。sendNotifications的時候,更多的可能是發給learner的批准消息,這時候他把所有participate當成leaner而自己是accepter。】

如果發送端server是looking狀態,先判斷該消息的提案號是否大於本server的提案號,如果是,說明收到了有更新的選舉被髮起,則更新本server的提案編號爲接收到的這個最新的提案號,同時清空記錄合法消息的集合recvset,更新本server的提案信息並向所有participate server發送notification消息,告知本server提案信息的改變。對應的代碼段:

zookeeper源碼學習(一)

 

如果消息發送端的提案號小於本server的提案號,則對該消息置之不理。

如果提案號相等,判斷本server所選舉的leader與消息該消息所選的leader編號的大小,如果消息中所選的leader編號更大,則更新本server的提案值,重新向所有節點發送notification消息。對應的代碼段:

zookeeper源碼學習(一)
 

【這個時候,是站在learner的角度,來判斷是否收到了足夠的消息結束這次選舉】

如果該消息是來自participate server的合法消息,將其放入到集合recvset中。處理完該消息之後,判斷此時是否已經收到了所有participate server的消息,或者收到了一個多數派的消息。代碼走到這裏,如果已經接收到了所有participate server的消息,說明所有這些回覆消息中沒有比proposedLeader(本server所選舉的leader)更大的提案了,那麼說明proposedLeader是目前公認最大的,所以proposedLeader贏得了選舉成爲leader,本server根據選舉結果設置自己的狀態。對應的代碼段:

zookeeper源碼學習(一)

 

如果沒有收到所有participate的回覆消息,但是本server選舉的leader(proposedLeader)得到了一個多數派的認可,這個時候不是立刻認定proposedLeader贏得了選舉,而是觀察一段時間(finalizeWait),如果在這段時間內沒有新的更高編號的提案到達,就可以確定proposedLeader贏得了選舉。對應的代碼段:

zookeeper源碼學習(一)

 

 

2)發送端server是observing狀態

不做任何處理

3)其他狀態(leading,following)

這裏不太理解。Outofelection存儲的應該是該算法instance中本輪選舉之外的消息,爲什麼要用它來做判斷呢,所有n.state != ServerState.LEADING的情況都放在一起處理?不管這兩個提案號之間相差多少?相關代碼段:

zookeeper源碼學習(一)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章