zookeeper 基本原理
一。zookeeper簡介
- zookeeper 是apache旗下的hadoop子專案,它一個開源的,分散式的服務協調器。同樣通過zookeeper可以實現服務間的同步與配置維護。通常情況下,在分散式應用開發中,協調服務這樣的工作不是件容易的事,很容易出現死鎖,不恰當的選舉競爭等。zookeeper就是擔負起了分散式協調的重擔。
zookeeper選舉機制
zookeeper 預設的演算法是 FastLeaderElection,採用投票數大於半數則勝出的邏輯。
相關內容:Zab協議、資料可以兩階段提交協議
1. 與選舉相關的概念
伺服器 ID
比如有三臺伺服器,編號分別是 1,2,3。
編號越大在選擇演算法中的權重越大。選舉狀態
LOOKING,競選狀態。
FOLLOWING,隨從狀態,同步 leader 狀態,參與投票。
OBSERVING,觀察狀態,同步 leader 狀態,不參與投票。
LEADING,領導者狀態。資料 ID
伺服器中存放的最新資料 version。
值越大說明資料越新,在選舉演算法中資料越新權重越大。邏輯時鐘
也叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個資料就會增加,然後與接收到的其它伺服器返回的投票資訊中的數值相比,根據不同的值做出不同的判斷。
2. 全新叢集選舉
假設目前有 5 臺伺服器,每臺伺服器均沒有資料,它們的編號分別是1,2,3,4,5,按編號依次啟動,它們的選擇舉過程如下:
- 伺服器 1 啟動,給自己投票,然後發投票資訊,由於其它機器還沒有啟動所以它收不到反饋資訊,伺服器 1 的狀態一直屬於 Looking。
- 伺服器 2 啟動,給自己投票,同時與之前啟動的伺服器 1 交換結果,由於伺服器 2 的編號大所以伺服器 2 勝出,但此時投票數沒有大於半數,所以兩個伺服器的狀態依然是 LOOKING。
- 伺服器 3 啟動,給自己投票,同時與之前啟動的伺服器 1,2 交換資訊,由於伺服器 3 的編號最大所以伺服器 3 勝出,此時投票數正好大於半數,所以伺服器 3 成為領導者,伺服器 1,2 成為小弟。
- 伺服器 4 啟動,給自己投票,同時與之前啟動的伺服器 1,2,3 交換資訊,儘管伺服器 4 的編號大,但之前伺服器 3 已經勝出,所以伺服器 4 只能成為小弟。
- 伺服器 5 啟動,後面的邏輯同伺服器 4 成為小弟。
3. 非全新叢集選舉(大約耗時200毫秒)
對於執行正常的 zookeeper 叢集,中途有機器 down 掉,需要重新選舉時,選舉過程就需要加入資料 ID、伺服器 ID 和邏輯時鐘。
**資料 ID:**資料新的 version 就大,資料每次更新都會更新 version。
**伺服器 ID:**就是我們配置的 myid 中的值,每個機器一個。
**邏輯時鐘:**這個值從 0 開始遞增,每次選舉對應一個值。 如果在同一次選舉中,這個值是一致的。
這樣選舉的標準就變成:- 邏輯時鐘小的選舉結果被忽略,重新投票;
- 統一邏輯時鐘後,資料 id 大的勝出;
- 資料 id 相同的情況下,伺服器 id 大的勝出;
4. 原子廣播
所有的寫操作請求被傳送給領導者,並通過廣播將更新資訊告訴跟隨者。當大部分跟隨者執行了修改之後,領導者就提交更新操作,客戶端將得到更新成功的迴應。未獲得一致性的協議被設計為原子的,因此無論修改失敗與否,他都分兩階段提交。
如果領導者出故障了,剩下存活的機器將會再次進行領導者選舉,並在新領導被選出前繼續執行任務。如果在不久後老的領導者恢復了,那麼它將以跟隨者的身份繼續執行。領導者選舉非常快,由釋出的結果所知,大約是200毫秒,因此在選舉是效能不會明顯減慢。
所有在ensemble中的機器在更新它們記憶體中的Znode樹之前會先將更新資訊寫入磁碟。讀操作請求可由任何機器服務,同時,由於他們只涉及記憶體查詢,因此非常快。
5. 疑惑
zookeeper是怎麼知道叢集大小的?
之前我們在搭建zookeeper叢集時,有一個檔案記錄了zookeeper叢集數量,忘記的可以看一下我之前的部落格:Linux上搭建zookeeper叢集,裡面有一個步驟是添加了node-1,node-2,node-3,到配置檔案中。
6. Zookeeper怎麼實現它的特性的(淺顯的理解)
1. 全域性資料一致:資料一致性是靠Paxos演算法保證的 假設有一個社團,其中有社長、社員(決議小組成員)兩個角色, 每個社員都可以接受外來的訊息,然後將訊息遞給社長處理。 然後社長向社員申請提案來修改社團制度 社員坐在一起,拿出自己收到的提案,對每個提案進行投票表決,超過半數通過即可生效 為了秩序,規定每個提案都有編號ID,按順序自增 每個社員都有一個社團制度筆記本,上面記著所有社團制度,和最近處理的提案編號,初始為0 投票通過的規則: 新提案ID 是否大於社員本中的ID,是社員舉手贊同 如果舉手人數大於社員人數的半數,即讓新提案生效 例如: 剛開始,每個社員本子上的ID都為0,現在有一個社員想社長提出:團費改為100元,社長收到後將這個提案的ID增加 1 每個社員都和自己ID對比,一看1>0,舉手贊同,同時修改自己本中的ID為1 發出提案的社長一看超過半數同意,就宣佈:1號提案生效 然後所有社員都修改自己筆記本中的團費為100元 以後任何一個社員諮詢任何一個社員:"團費是多少?",社員可以直接開啟筆記本檢視,並回答:團費為100元 可能會有極端的情況,就是多個社員一起發出了提案,就是併發的情況 例如 剛開始,每個議員本子上的編號都為0,現在有兩個議員(A和B)同時發出了提案,社長根據收到的先後順序對編號進行賦值(佇列), 那麼根據自增規則,這兩個提案的編號都為1,但只會有一個被先處理 假設A的提案在B的上面,議員們先處理A提案並通過了,這時,議員們的本子上的ID已經變為了1, 接下來處理B的提案,由於它的ID是1,不大於議員本子上的ID,B提案就被拒絕了,B議員需要重新發起提案 Paxos演算法解決的什麼問題呢,解決的就是保證每個節點執行相同的操作序列。好吧,這還不簡單,master維護一個全域性寫佇列,所有寫操作都必須 放入這個佇列編號,那麼無論我們寫多少個節點,只要寫操作是按編號來的,就能保證一致性。沒錯,就是這樣,可是如果master掛了呢。 Paxos演算法通過投票來對寫操作進行全域性編號,同一時刻,只有一個寫操作被批准,同時併發的寫操作要去爭取選票,只有獲得過半數選票的
- zookeeper的特點:
- 使用簡單:ZooKeeper允許分散式程式通過一個類似於標準檔案系統的共享的層次化名稱空間來相互協調。名稱空間由資料暫存器(稱為znode)組成,在ZooKeeper中,它們類似於檔案和目錄。與為儲存而設計的典型檔案系統不同,ZooKeeper資料儲存在記憶體中,這意味著ZooKeeper可以達到高吞吐量和低延遲數
- 同步與複製:組成ZooKeeper服務的伺服器必須互相有感知。客戶端連線到一個ZooKeeper伺服器。客戶端維護一個TCP連線,通過它傳送請求、獲取響應、獲取觀察事件和傳送心跳。如果連線到伺服器的TCP連線中斷,客戶端將連線到另一個伺服器。
- 有序
- 在進行大量讀操作時,執行速度奇快
- ZooKeeper提供的名稱空間非常類似於標準檔案系統。名稱是由斜槓(/)分隔的路徑元素序列。在ZooKeeper的名稱空間中,每一個節點都是通過一條路徑來標識的。如圖所示 :
- 當然zookeeper與標準檔案系統不同的是,它的節點分為永久節點和臨時節點(隨著會話斷開而消失)
注意以下幾點:
a.不能刪除已經存在子節點的節點
b.不能再臨時節點上建立節點
- 客戶端的節點都會被設定一個監控,當znode發生更改時,這個變化會通知所有客戶端然後刪除
zookeeper與eureka淺談
一個分散式系統不可能同時滿足C(一致性)、A(可用性)和P(分割槽容錯性)
zookeeper優先保證CP,當服務發生故障會進行leader的選舉,整個期間服務處在不可用狀態,如果選舉時間過長勢必會大幅度降低效能,另外就用途來說zookeeper偏向於服務的協調,當然含有註冊中心的作用
eureka優先保證AP, 即服務的節點各個都是平等的,沒有leader不leader一說, 當服務發生故障時,其餘的節點仍然可以提供服務,因此在出現故障時,效能表現優於zookeeper,但是可能會造成資料不一致的情況。