zookeeper原理


文中包含的幾個部分的圖片無法顯示,可以到: http://note.youdao.com/share/?id=017aeefa591b6e4c44aa7d5b84836ce0&type=note查看全文,

文中的各個部分都給出了引用鏈接,也可以直接查看


 

目錄:

    1、zookeeper原理
    2、zookeeper工作原理之我的理解  


1、zookeeper原理

第一章 Zookeeper server

1.1  Zookeeper基本原理

 

1.1.1    Zookeeper的保證

l         順序性,client的updates請求都會根據它發出的順序被順序的處理;

l         原子性,  一個update操作要么成功要么失敗,沒有其他可能的結果;

l         一致的鏡像,client不論連接到哪個server,展示給它都是同一個視圖;

l         可靠性,一旦一個update被應用就被持久化了,除非另一個update請求更新了當前值

l         實時性,對於每個client它的系統視圖都是最新的

1.1.2    Zookeeper server角色

領導者(Leader) : 領導者不接受client的請求,負責進行投票的發起和決議,最終更新狀態。

跟隨者(Follower): Follower用於接收客戶請求並返回客戶結果。參與Leader發起的投票。

觀察者(observer): Oberserver可以接收客戶端連接,將寫請求轉發給leader節點。但是Observer不參加投票過程,只是同步leader的狀態。Observer為系統擴展提供了一種方法。

學習者 ( Learner ) : 和leader進行狀態同步的server統稱Learner,上述Follower和Observer都是Learner。

1.1.3    Zookeeper集群

 

通常Zookeeper由2n+1台servers組成,每個server都知道彼此的存在。每個server都維護的內存狀態鏡像以及持久化存儲的事務日志和快照。對於2n+1台server,只要有n+1台(大多數)server可用,整個系統保持可用。

系統啟動時,集群中的server會選舉出一台server為Leader,其它的就作為follower(這里先不考慮observer角色)。接着由follower來服務client的請求,對於不改變系統一致性狀態的讀操作,由follower的本地內存數據庫直接給client返回結果;對於會改變系統狀態的更新操作,則交由Leader進行提議投票,超過半數通過后返回結果給client。

二.Zookeeper server工作原理

Zookeeper的核心是原子廣播,這個機制保證了各個server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式和廣播模式。當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數server的完成了和leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和server具有相同的系統狀態。

一旦leader已經和多數的follower進行了狀態同步后,他就可以開始廣播消息了,即進入廣播狀態。這時候當一個server加入zookeeper服務中,它會在恢復模式下啟動,發現leader,並和leader進行狀態同步。待到同步結束,它也參與消息廣播。Zookeeper服務一直維持在Broadcast狀態,直到leader崩潰了或者leader失去了大部分的followers支持。

Broadcast模式極其類似於分布式事務中的2pc(two-phrase commit 兩階段提交):即leader提起一個決議,由followers進行投票,leader對投票結果進行計算決定是否通過該決議,如果通過執行該決議(事務),否則什么也不做。

廣播模式需要保證proposal被按順序處理,因此zk采用了遞增的事務id號(zxid)來保證。所有的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64為的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一個新的epoch。低32位是個遞增計數。

當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的server都恢復到一個正確的狀態。

首先看一下選舉的過程,zk的實現中用了基於paxos算法(主要是fastpaxos)的實現。具體如下:

1.每個Server啟動以后都詢問其它的Server它要投票給誰。

2.對於其他server的詢問,server每次根據自己的狀態都回復自己推薦的leader的id和上一次處理事務的zxid(系統啟動時每個server都會推薦自己)

3.收到所有Server回復以后,就計算出zxid最大的哪個Server,並將這個Server相關信息設置成下一次要投票的Server。

4.計算這過程中獲得票數最多的的sever為獲勝者,如果獲勝者的票數超過半數,則改server被選為leader。否則,繼續這個過程,直到leader被選舉出來。

此外恢復模式下,如果是重新剛從崩潰狀態恢復的或者剛啟動的的server還會從磁盤快照中恢復數據和會話信息。(zk會記錄事務日志並定期進行快照,方便在恢復時進行狀態恢復)

選完leader以后,zk就進入狀態同步過程。

1.leader就會開始等待server連接

2.Follower連接leader,將最大的zxid發送給leader

3.Leader根據follower的zxid確定同步點

4.完成同步后通知follower 已經成為uptodate狀態

5.Follower收到uptodate消息后,又可以重新接受client的請求進行服務了。

三. ZookeeperServer工作流程

3.1.1 主線程的工作:

1. 剛開始時各個Server處於一個平等的狀態peer

2. 主線程加載配置后啟動。

3. 主線程啟動QuorumPeer線程,該線程負責管理多數協議(Quorum),並根據表決結果進行角色的狀態轉換。

4. 然后主線程等待QuorumPeer線程。

3.1.2  QuorumPeer線程

1. 首先會從磁盤恢復zkdatabase(內存數據庫),並進行快照回復。

2. 然后啟動server的通信線程,准備接收client的請求。

3. 緊接着該線程進行選舉leader准備,選擇選舉算法,啟動response線程(根據自身狀態)向其他server回復推薦的leaer。

4. 剛開始的時候server都處於looking狀態,進行選舉根據選舉結果設置自己的狀態和角色。

3.1.3 quorumPeer有幾種狀態

1. Looking: 尋找狀態,這個狀態不知道誰是leader,會發起leader選舉

2. Observing: 觀察狀態,這時候observer會觀察leader是否有改變,然后同步leader的狀態

3. Following:  跟隨狀態,接收leader的proposal ,進行投票。並和leader進行狀態同步

4. Leading:    領導狀態,對Follower的投票進行決議,將狀態和follower進行同步

當一個Server發現選舉的結果自己是Leader把自己的狀態改成Leading,如果Server推薦了其他人為Server它將自己的狀態改成Following。做Leader的server如果發現擁有的follower少於半數時,它重新進入looking狀態,重新進行leader選舉過程。(Observing狀態是根據配置設置的)。

3.2 Leader的工作流程:

 

3.2.1 Leader主線程:

1.首先leader開始恢復數據和清除session

啟動zk實例,建立請求處理鏈(Leader的請求處理鏈):PrepRequestProcessor->ProposalRequestProcessor->CommitProcessor->Leader.ToBeAppliedRequestProcessor ->FinalRequestProcessor

2.得到一個新的epoch,標識一個新的leader , 並獲得最大zxid(方便進行數據同步)

3.建立一個學習者接受線程(來接受新的followers的連接,follower連接后確定followers的zxvid號,來確定是需要對follower進行什么同步措施,比如是差異同步(diff),還是截斷(truncate)同步,還是快照同步)

4. 向follower建立一個握手過程leader->follower NEWLEADER消息,並等待直到多數server發送了ack

5. Leader不斷的查看已經同步了的follower數量,如果同步數量少於半數,則回到looking狀態重新進行leaderElection過程,否則繼續step5.

3.2.2 LearnerCnxAcceptor線程

1.該線程監聽Learner的連接

2.接受Learner請求,並為每個Learner創建一個LearnerHandler來服務

3.2.3 LearnerHandler線程的服務流程

1.檢查server來的第一個包是否為follower.info或者observer.info,如果不是則無法建立握手。

2. 得到Learner的zxvid,對比自身的zxvid,確定同步點

3.和Learner建立第二次握手,向Learner發送NEWLEADER消息

4.與server進行數據同步。

5.同步結束,知會server同步已經ok,可以接收client的請求。

6. 不斷讀取follower消息判斷消息類型

i.           如果是LEADER.ACK,記錄follower的ack消息,超過半數ack,將proposal提交(Commit)

ii.         如果是LEADER.PING,則維持session(延長session失效時間)

iii.        如果是LEADER.REQEST,則將request放入請求鏈進行處理–Leader寫請求發起proposal,然后根據follower回復的結果來確定是否commit的。最后由FinallRequestProcessor來實際進行持久化,並回復信息給相應的response給server

3.3 Follower的工作流程:

1.啟動zk實例,建立請求處理鏈:FollowerRequestProcessor->CommitProcessor->FinalProcessor

2.follower首先會連接leader,並將zxid和id發給leader

3.接收NEWLEADER消息,完成握手過程。

4.同leader進行狀態同步

5.完成同步后,follower可以接收client的連接

5.接收到client的請求,根據請求類型

l         對於寫操作, FollowerRequestProcessor會將該操作作為LEADER.REQEST發給LEADER由LEADER發起投票。

l         對於讀操作,則通過請求處理鏈的最后一環FinalProcessor將結果返回給客戶端

對於observer的流程不再贅述,observer流程和Follower的唯一不同的地方就是observer不會參加leader發起的投票。

三.關於Zookeeper的擴展

為了提高吞吐量通常我們只要增加服務器到Zookeeper集群中。但是當服務器增加到一定程度,會導致投票的壓力增大從而使得吞吐量降低。因此我們引出了一個角色:Observer。

Observers 的需求源於 ZooKeeper  follower服務器在上述工作流程中實際扮演了兩個角色。它們從客戶端接受連接與操作請求,之后對操作結果進行投票。這兩個職能在 ZooKeeper集群擴展的時候彼此制約。如果我們希望增加 ZooKeeper 集群服務的客戶數量(我們經常考慮到有上萬個客戶端的情況),那么我們必須增加服務器的數量,來支持這么多的客戶端。然而,從一致性協議的描述可以看到,增加服務器的數量增加了對協議的投票部分的壓力。領導節點必須等待集群中過半數的服務器響應投票。於是,節點的增加使得部分計算機運行較慢,從而拖慢整個投票過程的可能性也隨之提高,投票操作的會隨之下降。這正是我們在實際操作中看到的問題——隨着 ZooKeeper 集群變大,投票操作的吞吐量會下降。

所以需要增加客戶節點數量的期望和我們希望保持較好吞吐性能的期望間進行權衡。要打破這一耦合關系,引入了不參與投票的服務器,稱為 Observers。 Observers 可以接受客戶端的連接,將寫請求轉發給領導節點。但是,領導節點不會要求 Observers 參加投票。相反,Observers 不參與投票過程,僅僅和其他服務節點一起得到投票結果。

這個簡單的擴展給 ZooKeeper 的可伸縮性帶來了全新的鏡像。我們現在可以加入很多 Observers 節點,而無須擔心嚴重影響寫吞吐量。規模伸縮並非無懈可擊——協議中的一歩(通知階段)仍然與服務器的數量呈線性關系。但是,這里的穿行開銷非常低。因此可以認為在通知服務器階段的開銷無法成為主要瓶頸。

上圖顯示了一個簡單評測的結果。縱軸是從一個單一的客戶端發出的每秒鍾同步寫操作的數量。橫軸是 ZooKeeper 集群的尺寸。藍色的是每個服務器都是 voting 服務器的情況,而綠色的則只有三個是 voting 服務器,其它都是 Observers。圖中看到,擴充 Observers,寫性能幾乎可以保持不變,但如果同時擴展 voting 節點的數量的話,性能會明顯下降。顯然 Observers 是有效的。因此Observer可以用於提高Zookeeper的伸縮性。

此外Observer還可以成為特定場景下,廣域網部署的一種方案。原因有三點:1.為了獲得更好的讀性能,需要讓客戶端足夠近,但如果將投票服務器分布在兩個數據中心,投票的延遲太大會大幅降低吞吐,是不可取的。因此希望能夠不影響投票過程,將投票服務器放在同一個IDC進行部署,Observer可以跨IDC部署。2. 投票過程中,Observer和leader之間的消息、要遠小於投票服務器和server的消息,這樣遠程部署對帶寬要求就較小。3.由於Observers即使失效也不會影響到投票集群,這樣如果數據中心間鏈路發生故障,不會影響到服務本身的可用性。這種故障的發生概率要遠高於一個數據中心中機架間的連接的故障概率,所以不依賴於這種鏈路是個優點。

 



 2、 zookeeper工作原理2  

link:http://stblog.baidu-tech.com/?p=1164

ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,它包含一個簡單的原語集,分布式應用程序可以基於它實現同步服務,配置維護和命名服務等。Zookeeper是hadoop的一個子項目,其發展歷程無需贅述。在分布式應用中,由於工程師不能很好地使用鎖機制,以及基於消息的協調機制不適合在某些應用中使用,因此需要有一種可靠的、可擴展的、分布式的、可配置的協調機制來統一系統的狀態。Zookeeper的目的就在於此。本文簡單分析zookeeper的工作原理,對於如何使用zookeeper不是本文討論的重點。

 

1 Zookeeper的基本概念

1.1 角色

Zookeeper中的角色主要有以下三類,如下表所示:

系統模型如圖所示:

1.2 設計目的

1.最終一致性:client不論連接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。

2 .可靠性:具有簡單、健壯、良好的性能,如果消息m被到一台服務器接受,那么它將被所有的服務器接受。

3 .實時性:Zookeeper保證客戶端將在一個時間間隔范圍內獲得服務器的更新信息,或者服務器失效的信息。但由於網絡延時等原因,Zookeeper不能保證兩個客戶端能同時得到剛更新的數據,如果需要最新數據,應該在讀數據之前調用sync()接口。

4 .等待無關(wait-free):慢的或者失效的client不得干預快速的client的請求,使得每個client都能有效的等待。

5.原子性:更新只能成功或者失敗,沒有中間狀態。

6 .順序性:包括全局有序和偏序兩種:全局有序是指如果在一台服務器上消息a在消息b前發布,則在所有Server上消息a都將在消息b前被發布;偏序是指如果一個消息b在消息a后被同一個發送者發布,a必將排在b前面。

2 ZooKeeper的工作原理

Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。

為了保證事務的順序一致性,zookeeper采用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。

每個Server在工作過程中有三種狀態:

  • LOOKING:當前Server不知道leader是誰,正在搜尋
  • LEADING:當前Server即為選舉出來的leader
  • FOLLOWING:leader已經選舉出來,當前Server與之同步

2.1 選主流程

當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的Server都恢復到一個正確的狀態。Zk的選舉算法有兩種:一種是基於basic paxos實現的,另外一種是基於fast paxos算法實現的。系統默認的選舉算法為fast paxos。先介紹basic paxos流程:

  1. 1 .選舉線程由當前Server發起選舉的線程擔任,其主要功能是對投票結果進行統計,並選出推薦的Server;
  2. 2 .選舉線程首先向所有Server發起一次詢問(包括自己);
  3. 3 .選舉線程收到回復后,驗證是否是自己發起的詢問(驗證zxid是否一致),然后獲取對方的id(myid),並存儲到當前詢問對象列表中,最后獲取對方提議的leader相關信息(id,zxid),並將這些信息存儲到當次選舉的投票記錄表中;
  4. 4.  收到所有Server回復以后,就計算出zxid最大的那個Server,並將這個Server相關信息設置成下一次要投票的Server;
  5. 5.  線程將當前zxid最大的Server設置為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數, 設置當前推薦的leader為獲勝的Server,將根據獲勝的Server相關信息設置自己的狀態,否則,繼續這個過程,直到leader被選舉出來。

通過流程分析我們可以得出:要使Leader獲得多數Server的支持,則Server總數必須是奇數2n+1,且存活的Server的數目不得少於n+1.

每個Server啟動后都會重復以上流程。在恢復模式下,如果是剛從崩潰狀態恢復的或者剛啟動的server還會從磁盤快照中恢復數據和會話信息,zk會記錄事務日志並定期進行快照,方便在恢復時進行狀態恢復。選主的具體流程圖如下所示:

fast paxos流程是在選舉過程中,某Server首先向所有Server提議自己要成為leader,當其它Server收到提議以后,解決epoch和zxid的沖突,並接受對方的提議,然后向對方發送接受提議完成的消息,重復這個流程,最后一定能選舉出Leader。其流程圖如下所示:

2.2 同步流程

選完leader以后,zk就進入狀態同步過程。

  1. 1. leader等待server連接;
  2. 2 .Follower連接leader,將最大的zxid發送給leader;
  3. 3 .Leader根據follower的zxid確定同步點;
  4. 4 .完成同步后通知follower 已經成為uptodate狀態;
  5. 5 .Follower收到uptodate消息后,又可以重新接受client的請求進行服務了。

流程圖如下所示:

2.3 工作流程

2.3.1 Leader工作流程

Leader主要有三個功能:

  1. 1 .恢復數據;
  2. 2 .維持與Learner的心跳,接收Learner請求並判斷Learner的請求消息類型;
  3. 3 .Learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據不同的消息類型,進行不同的處理。

PING消息是指Learner的心跳信息;REQUEST消息是Follower發送的提議信息,包括寫請求及同步請求;ACK消息是Follower的對提議的回復,超過半數的Follower通過,則commit該提議;REVALIDATE消息是用來延長SESSION有效時間。
Leader的工作流程簡圖如下所示,在實際實現中,流程要比下圖復雜得多,啟動了三個線程來實現功能。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.3.2 Follower工作流程

Follower主要有四個功能:

  1. 1. 向Leader發送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
  2. 2 .接收Leader消息並進行處理;
  3. 3 .接收Client的請求,如果為寫請求,發送給Leader進行投票;
  4. 4 .返回Client結果。

Follower的消息循環處理如下幾種來自Leader的消息:

  1. 1 .PING消息: 心跳消息;
  2. 2 .PROPOSAL消息:Leader發起的提案,要求Follower投票;
  3. 3 .COMMIT消息:服務器端最新一次提案的信息;
  4. 4 .UPTODATE消息:表明同步完成;
  5. 5 .REVALIDATE消息:根據Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受消息;
  6. 6 .SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。

Follower的工作流程簡圖如下所示,在實際實現中,Follower是通過5個線程來實現功能的。

對於observer的流程不再敘述,observer流程和Follower的唯一不同的地方就是observer不會參加leader發起的投票。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM