最近在學習zookeeper,發現zk真的是一個優秀的中間件。在分佈式環境下,能夠高效解決數據管理問題。在學習的過程當中,要深刻zk的工做原理,並根據其特性作一些簡單的分佈式環境下數據管理工具。本文首先對zk的工做原理和相關概念作一下介紹,而後帶你們作一個簡單的分佈式配置中心。html
zookeeper是一個分佈式協調框架,主要是解決分佈式應用中常常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理、分佈式鎖等。node
# ls /path服務器
#create /path data網絡
#set /path data架構
#delete /path併發
#get /path框架
1)KeeperState.Expired:客戶端和服務器在ticktime的時間週期內,是要發送心跳通知的。這是租約協議的一個實現。客戶端發送request,告訴服務器其上一個租約時間,服務器收到這個請求後,告訴客戶端其下一個租約時間是哪一個時間點。當客戶端時間戳達到最後一個租約時間,而沒有收到服務器發來的任何新租約時間,即認爲本身下線(此後客戶端會廢棄此次鏈接,並試圖從新創建鏈接)。這個過時狀態就是Expired狀態分佈式
2)KeeperState.Disconnected:就像上面那個狀態所述,當客戶端斷開一個鏈接(多是租約期滿,也多是客戶端主動斷開)這是客戶端和服務器的鏈接就是Disconnected狀態高併發
3)KeeperState.SyncConnected:一旦客戶端和服務器的某一個節點創建鏈接(注意,雖然集羣有多個節點,可是客戶端一次鏈接到一個節點就好了),並完成一次version、zxid的同步,這時的客戶端和服務器的鏈接狀態就是SyncConnected工具
4)KeeperState.AuthFailed:ookeeper客戶端進行鏈接認證失敗時,發生該狀態
文件系統 + 監聽機制
同一個目錄下文件名稱不能重複,一樣zookeeper也是這樣的,zookeeper中統一叫做znode。znode節點能夠包含子znode,也能夠同時包含數據。znode只適合存儲很是小的數據,不能超過1M,最好都小於1K。
臨時節點(EPHEMERAL):客戶端關閉zk鏈接後清除
永久節點(persistent):持久化節點,除非客戶端主動刪除
有編號節點(Persistent_sequential):自動增長順序編號的znode持久化節點
臨時有編號(Ephemral_ sequential):臨時自動編號設置,znode節點編號會自動增長,可是會客戶端鏈接斷開而消失。分佈式鎖用的是這個類型的節點。
注:EPHEMERAL 臨時類型的節點不能有子節點,對於zk來講,有幾個節點數據就會存儲幾份。
客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、節點刪除、子目錄節 點增長刪除)時,zookeeper會通知客戶端。
一、客戶端啓動時向zookeeper服務器註冊信息
二、客戶端啓動同時註冊一系列的Watcher類型的監聽器到本地的WatchManager中
三、zookeeper服務器中節點發生變化後,觸發watcher事件後通知給客戶端,客戶端線程從WatcherManager中取出對應的Watcher對象來執行回調邏輯。
EventType.NodeCreated:當znode節點被建立時,該事件被觸發。
EventType.NodeChildrenChanged:當znode節點的直接子節點被建立、被刪除、子節點數據發生變動時,該事件被觸發。
EventType.NodeDataChanged:當znode節點的數據發生變動時,該事件被觸發。
EventType.NodeDeleted:當znode節點被刪除時,該事件被觸發。
EventType.None:當zookeeper客戶端的鏈接狀態發生變動時,即KeeperState.Expired、KeeperState.Disconnected、KeeperState.SyncConnected、KeeperState.AuthFailed狀態切換時,描述的事件類型爲EventType.None。
LOOKING:當前server不知道leader是誰,正在選舉
LEADING:當前server即爲選舉出來的leader
FOLLOWING:leader已經選舉出來,當前server是follower
ZAB 協議全稱:Zookeeper Atomic Broadcast(Zookeeper 原子廣播協議)。
ZAB 協議做用:解決分佈式數據管理一致性。
ZAB 協議定義:ZAB 協議是爲分佈式協調服務 Zookeeper 專門設計的一種支持 崩潰恢復 和 消息廣播 協議。
基於該協議,Zookeeper 實現了一種 主備模式 的系統架構來保持集羣中各個副本之間數據一致性。
zookeeper集羣採用主從(leader-follower)模式保證服務高可用。leader節點可讀可寫,follower節點只讀,這種模式就須要保證leader節點和follower節點的數據一致性。對於客戶端發送的寫請求,所有由 Leader 接收,Leader 將請求封裝成一個事務 Proposal,將其發送給全部 Follwer ,而後,根據全部 Follwer 的反饋,若是超過半數成功響應,則執行 commit 操做(先提交本身,再發送 commit 給全部 Follwer)。
注:上述中有一個概念:兩階段提交過程(分佈式系統中數據一致性常常會涉及到的方案)。follower節點是能夠處理寫請求的,會轉發給leader節點。leader節點經過消息廣播(二階段提交)同步寫操做到follower節點,保證數據一致性。
zookeeper中每一個事務都對應一個ZXID(全局的、惟一的、順序的)。ZXID 是一個 64 位的數字,其中低 32 位能夠看做是一個簡單的遞增的計數器,針對客戶端的每個事務請求,Leader 都會產生一個新的事務 Proposal 並對該計數器進行 + 1 操做。而高 32 位則表明了 Leader 服務器上取出本地日誌中最大事務 Proposal 的 ZXID,並從該 ZXID 中解析出對應的 epoch 值,而後再對這個值加一。
即若是在消息廣播的過程當中,leader死掉了,如何保證數據的一致性問題。
假設兩種異常狀況:
一、一個事務在 Leader 上提交了,而且過半的 Folower 都響應 Ack 了,可是 Leader 在 Commit 消息發出以前掛了。
二、假設一個事務在 Leader 提出以後,Leader 掛了。
考慮到上述兩種異常狀況,Zab 協議崩潰恢復要求知足如下兩個要求:
1)確保已經被 Leader 提交的 Proposal 必須最終被全部的 Follower 服務器提交。
2)確保丟棄已經被 Leader 提出的可是沒有被提交的 Proposal。
崩潰恢復主要包含:leader選舉 和 數據恢復。
leader選舉:
一、要求 可用節點數量 > 總節點數量/2 。注意 是 > , 不是 ≥。
二、新選舉出來的 Leader 不能包含未提交的 Proposal(新選舉的 Leader 必須都是已經提交了 Proposal 的 Follower 服務器節點) 、新選舉的 Leader 節點中含有最大的 zxid(能夠避免 Leader 服務器檢查 Proposal 的提交和丟棄工做。若是zxid相同,選擇server_id【zoo.cfg中的myid】最大的。)
數據恢復:
一、上面講過了ZXID的高 32 位表明了每代 Leader 的惟一性,低 32 表明了每代 Leader 中事務的惟一性。同時,也能讓 Follwer 經過高 32 位識別不一樣的 Leader。簡化了數據恢復流程。
二、基於這樣的策略:當 Follower 連接上 Leader 以後,Leader 服務器會根據本身服務器上最後被提交的 ZXID 和 Follower 上的 ZXID 進行比對,比對結果要麼回滾,要麼和 Leader 同步。
集羣的腦裂一般是發生在節點之間通訊不可達的狀況下,集羣會分裂成不一樣的小集羣,小集羣各自選出本身的master節點,致使原有的集羣出現多個master節點的狀況。
只要咱們清楚集羣leader選舉的要求(可用節點數量 > 總節點數量/2 。注意 是 > , 不是 ≥),我相信很容易明白奇數節點集羣相比偶數節點的集羣有更大的優點。
一、發生腦裂(分紅2個小集羣)的狀況下,奇數節點的集羣總會有一個小集羣知足可用節點數量 > 總節點數量/2,因此zookeeper集羣總能選取出leader。
二、在容錯能力相同的狀況下,奇數集羣更節省資源。仍是要清楚leader選舉的要求哈,舉個列子:3個節點的集羣,若是集羣能夠正常工做(即leader選舉成功),至少須要2個節點是正常的;4個節點的集羣,若是集羣能夠正常工做(即leader選舉成功),至少須要3個節點是正常的。那麼3個節點的集羣和4個節點的集羣都有一個節點宕機的容錯能力。很明顯,在容錯能力相同的狀況下,奇數節點的集羣更節省資源。
在分佈式系統領域有個著名的 CAP定理(C- 數據一致性;A-服務可用性;P-服務對網絡分區故障的容錯性,這三個特性在任何分佈式系統中不能同時知足,最多同時知足兩個)。
zookeeper基於CP,即任什麼時候刻對ZooKeeper的訪問請求能獲得一致的數據結果,同時系統對網絡分割具有容錯性;可是它不能保證每次服務請求的可用性(注:也就 是在極端環境下,zookeeper可能會丟棄一些請求,消費者程序須要從新請求才能得到結果)。至於zookeeper爲啥不能保證服務的高可用,你們能夠想一下發生腦裂後沒法選取leader、選取leader過程當中丟棄某些請求。當網絡出現故障時,剩餘zk集羣server會發起投票選舉新的leader,可是此過程會持續30~120s,此過程對於高併發來講十分漫長,會致使整個註冊服務的癱瘓,這是不可容忍的。
Eureka基於AP,不會有相似於ZooKeeper的選舉leader的過程,採用的是Peer to Peer 對等通訊,沒有leader/follower的說法,每一個peer都是對等的;客戶端請求會自動切換 到新的Eureka節點;當宕機的服務器從新恢復後,Eureka會再次將其歸入到服務器集羣管理之中。當Eureka節點接受客戶端請求時,全部的操做都會在節點間進行復制(replicate To Peer)操做,將請求複製到該 Eureka Server 當前所知的其它全部節點中。至於爲啥Eureka不能保證數據一致性,源於Eureka的自我保護機制:若是在15分鐘內超過85%的節點都沒有正常的心跳,那麼Eureka就認爲客戶端與註冊中心出現了網絡故障,此時會出現如下幾種狀況:
1. Eureka再也不從註冊列表中移除由於長時間沒收到心跳而應該過時的服務 。
2. Eureka仍然可以接受新服務的註冊和查詢請求,可是不會被同步到其它節點上(即保證當前節點依然可用) 。
3. 當網絡穩定時,當前實例新的註冊信息會被同步到其它節點中。
所以, Eureka能夠很好的應對因網絡故障致使部分節點失去聯繫的狀況,而不會像zookeeper那樣使整個註冊服務癱瘓。
以上是對zookeeper的工做原理和相關概念的一些整理,但願能對你們認識zookeeper有所幫助。下一篇文章開始基於zookeeper作一個簡單的分佈式配置中心,敬請期待!!!
https://blog.csdn.net/pml18710973036/article/details/64121522