Zookeeper--數據同步

數據同步

ZooKeeper集羣服務器啓動的過程中,整個集羣完成Leader選舉之後,Learner 會向Leader 服務器進行註冊。當Learner 服務器向Leader完成註冊後,就進入數據同步環節。

簡單地講,數據同步過程就是Leader服務器將那些沒有在Learner服務器上提交過的事務請求同步給Learner服務器,大體過程如下圖所示。
在這裏插入圖片描述

獲取Learner狀態

在註冊Learner的最後階段,Learner服務器會發送給Leader服務器-一個ACKEPOCH數據包,Leader 會從這個數據包中解析出該Learner的currentEpoch和lastZxid。

數據同步初始化
在開始數據同步之前,Leader 服務器會進行數據同步初始化,首先會從ZooKeeper的內存數據庫中提取出事務請求對應的提議緩存隊列(用“提議緩存隊列”來指代該隊列): proposals, 同時完成對以下三個ZXID值的初始化。

  • peerLastZxid:該Learner服務器最後處理的ZXID。
  • minCommittedLog: Leader服務器提議緩存隊列committedLog中的最小ZXID。
  • maxCommittedLog:Leader服務器提議緩存隊列committedLog中的最大ZXID。

ZooKeeper集羣數據同步通常分爲四類,分別是:

  • 直接差異化同步(DIFF 同步)
  • 先回滾再差異化同步(TRUNC+DIFF 同步)
  • 僅回滾同步(TRUNC 同步)
  • 全量同步(SNAP同步)。

在初始化階段,Leader服務器會優先初始化以全量同步方式來同步數據。當然,這並非最終的數據同步方式,在以下步驟中,會根據Leader和Learner服務器之間的數據差異情況來決定最終的數據同步方式。

直接差異化同步(DIFF同步)

場景:peerlastZxid介於minCommittedLog和maxCommittedLog之間

對於這種場景,就使用直接差異化同步(DIFF 同步)方式即可。Leader 服務器會首先向這個Learner發送一個DIFF指令,用於通知Learner“進人差異化數據同步階段,Leader服務器即將把一些Proposal同步給自己”。

在實際Proposal同步過程中,針對每個Proposal,Leader服務器都會通過發送兩個數據包來完成,分別是PROPOSAL內容數據包和COMMIT指令數據包一這 和ZooKeeper運行時Leader和Follower之間的事務請求的提交過程是一致的。

舉個例子來說,假如某個時刻Leader服務器的提議緩存隊列對應的ZXID依次是:

0x500000001 0x500000002 0x500000003 0x500000004 0x500000005

而Learner服務器最後處理的ZXID爲0x500000003,於是Leader服務器就會依次將0x500000004和0x500000005 兩個提議同步給Learner 服務器,同步過程中的數據包發送順序如下:
在這裏插入圖片描述

通過以上四個數據包的發送,Learner服務器就可以接收到自己和Leader服務器的所有差異數據。Leader 服務器在發送完差異數據之後,就會將該Learner 加入到forwardingFollowers或observingLearners隊列中,這兩個隊列在ZooKeeper運行期間的事務請求處理過程中都會使用到。隨後Leader 還會立即發送一個NEWLEADER指令,用於通知Learner,已經將提議緩存隊列中的Proposal 都同步給自己了。

再來看Learner對Leader發送過來的數據包的處理。根據上面講解的Leader服務器的數據包發送順序,Learner會首先接收到一個DIFF指令,於是便確定了接下來進入DIFF同步階段。然後依次收到表中的四個數據包,Learner 會依次將其應用到內存數據庫中。緊接着,Learner還會接收到來自Leader 的NEWLEADER指令,此時Learner就會反饋給Leader一個ACK消息,表明自己也確實完成了對提議緩存隊列中Proposal的同步。

Leader在接收到來自Learner 的這個ACK消息以後,就認爲當前Learner已經完成了數據同步,同時進入“過半策略”等待階段——Leader 會和其他Learner 服務器進行上述同樣的數據同步流程,直到集羣中有過半的Learner機器響應了Leader這個ACK消息。一旦滿足“過半策略”後,Leader服務器就會向所有已經完成數據同步的Learner發送一個UPTODATE指令,用來通知Learner已經完成了數據同步,同時集羣中已經有過半機器完成了數據同步,集羣已經具備了對外服務的能力了。

Learner在接收到這個來自Leader的UPTODATE指令後,會終止數據同步流程,然後向Leader再次反饋一個ACK消息。

整個直接差異化通過過程中涉及的Leader和Learner之間的數據包通信入下圖:
在這裏插入圖片描述

先回滾再差異化同步(TRUNC+DIFF同步)

場景:針對上面的場景,我們已經介紹了直接差異化同步的詳細過程。但是在這種場景中,會有一個罕見但是確實存在的特殊場景:設有A、B、C三臺機器,假如某一時刻B是Leader服務器,此時的LeaderEpoch爲5,同時當前已經被集羣中絕大部分機器都提交的ZXID包括: 0x500000001和0x500000002。此時,Leader 正要處理ZXID:0x500000003,並且已經將該事務寫人到了Leader 本地的事務日誌中去一就在 Leader恰好要將該Proposal發送給其他Follower機器進行投票的時候,Leader服務器掛了,Proposal沒有被同步出去。此時ZooKeeper集羣會進行新一輪的Leader選舉,假設此次選舉產生的新的Leader是A,同時Leader_Epoch變更爲6,之後A和C兩臺服務器繼續對外進行服務,又提交了0x600000001 和0x600000002兩個事務。此時,服務器B再次啓動,並開始數據同步。

簡單地講,上面這個場景就是Leader服務器在已經將事務記錄到了本地事務日誌中,但是沒有成功發起Proposal流程的時候就掛了。在這個特殊場景中,我們看到,peerLastZxid、minCommittedLog和maxCommittedLog 的值分別是0x500000003、 0x500000001 和0x600000002,顯然,peerLastZxid 介於minCommittedLog和maxCommittedLog之間。

對於這個特殊場景,就使用先回滾再差異化同步(TRUNC+DIFF同步)的方式。當Leader服務器發現某個Learner包含了一條自己沒有的事務記錄,那麼就需要讓該Learner進行事務回滾一回滾到Leader服務器上存在的,同時也是最接近於peerLastZxid的ZXID。在上面這個例子中,Leader會需要Learner回滾到ZXID爲0x500000002的事務記錄。

先回滾再差異化同步的數據同步方式在具體實現上和差異化同步是一樣的,都是會將差,異化的Proposal發送給Learner。同步過程中的數據包發送順序如下表所示。
在這裏插入圖片描述

僅回滾同步(TRUNC同步)

場景:peerLastZxid大於maxCommittedLog

這種場景其實就是上述先回滾再差異化同步的簡化模式,Leader會要求Learner回滾到ZXID值爲maxCommitedLog對應的事務操作。

全量同步(SNAP同步)

場景1: peerLastZxid 小於minCommittedLog。

場景2: Leader 服務器上沒有提議緩存隊列,peerLastZxid 不等於lastProcessedZxid(Leader服務器數據恢復後得到的最大ZXID)。j

上述這兩個場景非常類似,在這兩種場景下,Leader服務器都無法直接使用提議緩存隊列和Learner進行數據同步,因此只能進行全量同步(SNAP 同步)。

所謂全量同步就是Leader服務器將本機上的全量內存數據都同步給Learner。Leader服務器首先向Learner發送一個 SNAP指令,通知Learner即將進行全量數據同步。後,Leader會從內存數據庫中獲取到全量的數據節點和會話超時時間記錄器,將它們序列化後傳輸給Learner。 Learner 服務器接收到該全量數據後,會對其反序列化後載入到內存數據庫中。

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