zookeeper基础整理
zookeeper簡述
????????ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件
????????ZooKeeper 使用 Java 所編寫,但是支持 Java 和 C 兩種編程語言。
提供的功能包括:
????????配置管理:集群中配置文件的同步
????????分布式鎖:解決分布式環境中數據同步問題
????????集群管理:負載均衡,容災處理等。
????????命名服務:
????????其他等等
1、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、zookeeper數據同步過程:
選完leader以后,zk就進入狀態同步過程。
1. leader等待server連接;
2 .Follower連接leader,將最大的zxid發送給leader;
3 .Leader根據follower的zxid確定同步點;
4 .完成同步后通知follower 已經成為uptodate狀態;
5 .Follower收到uptodate消息后,又可以重新接受client的請求進行服務了。
流程圖如下所示:
3、zookeeper工作流程
1、Leader工作流程
Leader主要有三個功能:
????????1 .恢復數據;
????????2 .維持與Learner的心跳,接收Learner請求并判斷Learner的請求消息類型;
???????3 .Learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據不同的消息類型,進行不同的處理。
????????PING消息是指Learner的心跳信息;
????????REQUEST消息是Follower發送的提議信息,包括寫請求及同步請求;
????????ACK消息是Follower的對提議的回復,超過半數的Follower通過,則commit該提議;
????????REVALIDATE消息是用來延長SESSION有效時間。
????????Leader的工作流程簡圖如下所示,在實際實現中,流程要比下圖復雜得多,啟動了三個線程來實現功能。
2、Follower工作流程
Follower主要有四個功能:
????????1. 向Leader發送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
????????2 .接收Leader消息并進行處理;
????????3 .接收Client的請求,如果為寫請求,發送給Leader進行投票;
????????4 .返回Client結果。
Follower的消息循環處理如下幾種來自Leader的消息:
????????1 .PING消息:心跳消息;
????????2 .PROPOSAL消息:Leader發起的提案,要求Follower投票;
????????3 .COMMIT消息:服務器端最新一次提案的信息;
????????4 .UPTODATE消息:表明同步完成;
????????5 .REVALIDATE消息:根據Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受消息;
????????6 .SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。
????????Follower的工作流程簡圖如下所示,在實際實現中,Follower是通過5個線程來實現功能的。
????????observer流程和Follower的唯一不同的地方就是observer不會參加leader發起的投票。
4、zookeeper中session的狀態
????????我們知道ZooKeeper允許客戶端創建兩種類型的節點:persistent、ephemeral,ephemeral類型的節點是與創建它的客戶端一起共存亡的。
????????那么這中間就有問題,ZooKeeper是如何知道客戶端還存不存在呢?
????????ZooKeeper是使用session來解決這個問題的,這也是為什么我們在客戶端創建ZooKeeper實例時需要傳入一個sessionout的參數。當客戶端與Follower連接時,實際上是成功創建了一個session,Follower和Leader都保存了這個session信息(實際上Session的建立也是需要Leader同意的)。一方面,客戶端會定期的向Follower發送Ping包來告訴這個Follower我還活著;另一方面,Leader也會定期向Follower發送ping包,一則檢測它的Follower們是否至少有超過一半還活著,二則Follower們返回他們各自正在服務的客戶端(未超時的session),來告訴Leader那些客戶端還活著,這樣Leader就可以刪除那些客戶端已經不存在的ephemeral類型的節點
5、zookeeper中的選舉算法
????????我們有一個zookeeper集群,有好幾個節點。每個節點都可以接收請求,處理請求。那么,如果這個時候分別有兩個客戶端向兩個節點發起請求,請求的內容是修改同一個數據。比如客戶端c1,請求節點n1,請求是set a = 1; 而客戶端c2,請求節點n2,請求內容是set a = 2;
那么最后a是等于1還是等于2呢? 這在一個分布式環境里是很難確定的。解決這個問題有很多辦法,而zookeeper的辦法是,我們選一個總統出來,所有的這類決策都提交給總統一個人決策,那之前的問題不就沒有了么。
????????如何在zookeeper集群中選舉出一個leader,zookeeper使用了三種算法,具體使用哪種算法,在配置文件中是可以配置的,對應的配置項是”electionAlg”,其中1對應的是LeaderElection算法,2對應的是AuthFastLeaderElection算法,3對應的是FastLeaderElection算法.默認使用FastLeaderElection算法.
logicalclock -》邏輯時鐘
Epoch -》 epoch,zxid的高32,表示leader的變動,選舉的輪數,即邏輯時鐘。Epoch會隨著選舉輪數的增加而遞增。
zxid -》 事務id號,每個操作都有一個zxid, 64位
server id -》配置的myid,服務器編號
1、第一階段:數據恢復階段
????????首先,每個在zookeeper服務器先讀取當前保存在磁盤的數據,zookeeper中的每份數據,都有一個對應的id值,這個值是依次遞增的,換言之,越新的數據,對應的ID值就越大.
2、第二階段:首次發送自己投票信息
????????在讀取數據完畢之后,每個zookeeper服務器發送自己選舉的leader,這個協議中包含了以下幾部分的數據:
????????2.1所選舉leader的id(就是配置文件中寫好的每個服務器的id) ,在初始階段,每臺服務器的這個值都是自己服務器的id,也就是它們都選舉自己為leader.
????????2.2 服務器最大數據的id,這個值大的服務器,說明存放了更新的數據.
????????2.3邏輯時鐘的值,這個值從0開始遞增,每次選舉對應一個值,也就是說
????????????????2.3.1 如果在同一次選舉中,那么這個值應該是一致的
????????????????2.3.2 邏輯時鐘值越大,說明這一次選舉leader的進程更新.
????????2.4 本機在當前選舉過程中的狀態,有以下幾種:LOOKING,FOLLOWING,OBSERVING,LEADING。
3、第三階段:接受其他機器的選舉信息
????????3.1如果所接收數據服務器的狀態還是在選舉階段(LOOKING 狀態),那么首先判斷邏輯時鐘值,又分為以下三種情況:
????????????????3.1.1:如果發送過來的邏輯時鐘大于目前的邏輯時鐘,那么說明這是更新的一次選舉,此時需要更新一下本機的邏輯時鐘值,同時將之前收集到的來自其他服務器的選舉清空,因為這些數據已經不再有效了.然后判斷是否需要更新當前自己的選舉情況.在這里是根據選舉leader id,保存的最大數據id來進行判斷的,這兩種數據之間對這個選舉結果的影響的權重關系是:首先看數據id,數據id大者勝出;其次再判斷leader id,leader id大者勝出.然后再將自身最新的選舉結果(也就是上面提到的三種數據廣播給其他服務器)
????????????????3.1.2: 發送過來數據的邏輯時鐘小于本機的邏輯時鐘,說明對方在一個相對較早的選舉進程中,這里只需要將本機的數據發送過去就是了.
????????????????3.1.3:兩邊的邏輯時鐘相同,此時也只是調用totalOrderPredicate函數判斷是否需要更新本機的數據(首先看數據id,數據id大者勝出;其次再判斷leader id,leader id大者勝出.),如果更新了再將自己最新的選舉結果廣播出去就是了
????????3.2:三種情況的處理完畢之后,再處理兩種情況:
????????????????3.2.1:服務器判斷是不是已經收集到了所有服務器的選舉狀態,如果是那么根據選舉結果設置自己的角色(FOLLOWING還是LEADER),然后退出選舉過程就是了.
????????????????3.2.2:即使沒有收集到所有服務器的選舉狀態,也可以判斷一下根據以上過程之后最新的選舉leader是不是得到了超過半數以上服務器的支持,如果是,那么嘗試在200ms內接收一下數據,如果沒有新的數據到來,說明大家都已經默認了這個結果,同樣也設置角色退出選舉過程.
????????3.3: 如果所接收服務器不在選舉狀態,也就是在FOLLOWING或者LEADING狀態,做以下兩個判斷:
????????????????3.3.1:如果邏輯時鐘相同,將該數據保存到recvset,如果所接收服務器宣稱自己是leader,那么將判斷是不是有半數以上的服務器選舉它,如果是則設置選舉狀態退出選舉過程
????????????????3.3.2 否則這是一條與當前邏輯時鐘不符合的消息,那么說明在另一個選舉過程中已經有了選舉結果,于是將該選舉結果加入到outofelection集合中,再根據outofelection來判斷是否可以結束選舉,如果可以也是保存邏輯時鐘,設置選舉狀態,退出選舉過程.(從這里可以看出,當某個節點已經確定選舉結果不再處于LOOKING狀態時,其收到LOOKING消息時都會直接回應選舉的最終結果。結合上面那個比方,相當于某次選舉結束了,這個時候來了選民4又發起一次新的選舉,那么其他選民就直接告訴它當前的Leader情況)
zookeeper原理白話說明:
????????Paxos描述了這樣一個場景,有一個叫做Paxos的小島(Island)上面住了一批居民,島上面所有的事情由一些特殊的人決定,他們叫做議員(Senator)。議員的總數(Senator Count)是確定的,不能更改。島上每次環境事務的變更都需要通過一個提議(Proposal),每個提議都有一個編號(PID),這個編號是一直增長的,不能倒退。每個提議都需要超過半數((Senator Count)/2 +1)的議員同意才能生效。每個議員只會同意大于當前編號的提議,包括已生效的和未生效的。如果議員收到小于等于當前編號的提議,他會拒絕,并告知對方:你的提議已經有人提過了。這里的當前編號是每個議員在自己記事本上面記錄的編號,他不斷更新這個編號。整個議會不能保證所有議員記事本上的編號總是相同的。現在議會有一個目標:保證所有的議員對于提議都能達成一致的看法。
????????好,現在議會開始運作,所有議員一開始記事本上面記錄的編號都是0。有一個議員發了一個提議:將電費設定為1元/度。他首先看了一下記事本,嗯,當前提議編號是0,那么我的這個提議的編號就是1,于是他給所有議員發消息:1號提議,設定電費1元/度。其他議員收到消息以后查了一下記事本,哦,當前提議編號是0,這個提議可接受,于是他記錄下這個提議并回復:我接受你的1號提議,同時他在記事本上記錄:當前提議編號為1。發起提議的議員收到了超過半數的回復,立即給所有人發通知:1號提議生效!收到的議員會修改他的記事本,將1好提議由記錄改成正式的法令,當有人問他電費為多少時,他會查看法令并告訴對方:1元/度。
????????現在看沖突的解決:假設總共有三個議員S1-S3,S1和S2同時發起了一個提議:1號提議,設定電費。S1想設為1元/度, S2想設為2元/度。結果S3先收到了S1的提議,于是他做了和前面同樣的操作。緊接著他又收到了S2的提議,結果他一查記事本,咦,這個提議的編號小于等于我的當前編號1,于是他拒絕了這個提議:對不起,這個提議先前提過了。于是S2的提議被拒絕,S1正式發布了提議: 1號提議生效。S2向S1或者S3打聽并更新了1號法令的內容,然后他可以選擇繼續發起2號提議。
????????好,我覺得Paxos的精華就這么多內容。現在讓我們來對號入座,看看在ZK Server里面Paxos是如何得以貫徹實施的
小島(Island)——ZK Server Cluster
議員(Senator)——ZK Server
提議(Proposal)——ZNode Change(Create/Delete/SetData…)
提議編號(PID)——Zxid(ZooKeeper Transaction Id)
正式法令——所有ZNode及其數據
????????貌似關鍵的概念都能一一對應上,但是等一下,Paxos島上的議員應該是人人平等的吧,而ZK Server好像有一個Leader的概念。沒錯,其實Leader的概念也應該屬于Paxos范疇的。如果議員人人平等,在某種情況下會由于提議的沖突而產生一個“活鎖”(所謂活鎖我的理解是大家都沒有死,都在動,但是一直解決不了沖突問題)。Paxos的作者Lamport在他的文章”The Part-Time Parliament“中闡述了這個問題并給出了解決方案——在所有議員中設立一個總統,只有總統有權發出提議,如果議員有自己的提議,必須發給總統并由總統來提出。好,我們又多了一個角色:總統。
總統——ZK Server Leader
????????又一個問題產生了,總統怎么選出來的?oh, my god! It’s a long story.
現在我們假設總統已經選好了,下面看看ZK Server是怎么實施的。
情況一:
????????屁民甲(Client)到某個議員(ZK Server)那里詢問(Get)某條法令的情況(ZNode的數據),議員毫不猶豫的拿出他的記事本(local storage),查閱法令并告訴他結果,同時聲明:我的數據不一定是最新的。你想要最新的數據?沒問題,等著,等我找總統Sync一下再告訴你。
情況二:
????????屁民乙(Client)到某個議員(ZK Server)那里要求政府歸還欠他的一萬元錢,議員讓他在辦公室等著,自己將問題反映給了總統,總統詢問所有議員的意見,多數議員表示欠屁民的錢一定要還,于是總統發表聲明,從國庫中拿出一萬元還債,國庫總資產由100萬變成99萬。屁民乙拿到錢回去了(Client函數返回)。
情況三:
????????總統突然掛了,議員接二連三的發現聯系不上總統,于是各自發表聲明,推選新的總統,總統大選期間政府停業,拒絕屁民的請求。
總結
以上是生活随笔為你收集整理的zookeeper基础整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分组密码的工作模式
- 下一篇: 三、比特币白皮书:一种点对点的电子现金系