基于zookeeper实现分布式配置中心(一)
最近在學(xué)習(xí)zookeeper,發(fā)現(xiàn)zk真的是一個優(yōu)秀的中間件。在分布式環(huán)境下,可以高效解決數(shù)據(jù)管理問題。在學(xué)習(xí)的過程中,要深入zk的工作原理,并根據(jù)其特性做一些簡單的分布式環(huán)境下數(shù)據(jù)管理工具。本文首先對zk的工作原理和相關(guān)概念做一下介紹,然后帶大家做一個簡單的分布式配置中心。
zookeeper介紹
zookeeper是一個分布式協(xié)調(diào)框架,主要是解決分布式應(yīng)用中經(jīng)常遇到的一些數(shù)據(jù)管理問題,如:統(tǒng)一命名服務(wù)、狀態(tài)同步服務(wù)、集群管理、分布式應(yīng)用配置項(xiàng)的管理、分布式鎖等。
zookeeper使用
查看節(jié)點(diǎn)
# ls /path
創(chuàng)建節(jié)點(diǎn)
#create /path data
修改節(jié)點(diǎn)
#set /path data
刪除節(jié)點(diǎn)
#delete /path
獲取節(jié)點(diǎn)數(shù)據(jù)
#get /path
zookeeper C/S連接狀態(tài)
1)KeeperState.Expired:客戶端和服務(wù)器在ticktime的時間周期內(nèi),是要發(fā)送心跳通知的。這是租約協(xié)議的一個實(shí)現(xiàn)。客戶端發(fā)送request,告訴服務(wù)器其上一個租約時間,服務(wù)器收到這個請求后,告訴客戶端其下一個租約時間是哪個時間點(diǎn)。當(dāng)客戶端時間戳達(dá)到最后一個租約時間,而沒有收到服務(wù)器發(fā)來的任何新租約時間,即認(rèn)為自己下線(此后客戶端會廢棄這次連接,并試圖重新建立連接)。這個過期狀態(tài)就是Expired狀態(tài)
2)KeeperState.Disconnected:就像上面那個狀態(tài)所述,當(dāng)客戶端斷開一個連接(可能是租約期滿,也可能是客戶端主動斷開)這是客戶端和服務(wù)器的連接就是Disconnected狀態(tài)
3)KeeperState.SyncConnected:一旦客戶端和服務(wù)器的某一個節(jié)點(diǎn)建立連接(注意,雖然集群有多個節(jié)點(diǎn),但是客戶端一次連接到一個節(jié)點(diǎn)就行了),并完成一次version、zxid的同步,這時的客戶端和服務(wù)器的連接狀態(tài)就是SyncConnected
4)KeeperState.AuthFailed:ookeeper客戶端進(jìn)行連接認(rèn)證失敗時,發(fā)生該狀態(tài)
zookeeper工作原理
文件系統(tǒng) + 監(jiān)聽機(jī)制
文件系統(tǒng)特點(diǎn)
同一個目錄下文件名稱不能重復(fù),同樣zookeeper也是這樣的,zookeeper中統(tǒng)一叫作znode。znode節(jié)點(diǎn)可以包含子znode,也可以同時包含數(shù)據(jù)。znode只適合存儲非常小的數(shù)據(jù),不能超過1M,最好都小于1K。
znode節(jié)點(diǎn)類型
臨時節(jié)點(diǎn)(EPHEMERAL):客戶端關(guān)閉zk連接后清除
永久節(jié)點(diǎn)(persistent):持久化節(jié)點(diǎn),除非客戶端主動刪除
有編號節(jié)點(diǎn)(Persistent_sequential):自動增加順序編號的znode持久化節(jié)點(diǎn)
臨時有編號(Ephemral_ sequential):臨時自動編號設(shè)置,znode節(jié)點(diǎn)編號會自動增加,但是會客戶端連接斷開而消失。分布式鎖用的是這個類型的節(jié)點(diǎn)。
注:EPHEMERAL?臨時類型的節(jié)點(diǎn)不能有子節(jié)點(diǎn),對于zk來說,有幾個節(jié)點(diǎn)數(shù)據(jù)就會存儲幾份。
監(jiān)聽機(jī)制
客戶端注冊監(jiān)聽它關(guān)心的目錄節(jié)點(diǎn),當(dāng)目錄節(jié)點(diǎn)發(fā)生變化(數(shù)據(jù)改變、節(jié)點(diǎn)刪除、子目錄節(jié) 點(diǎn)增加刪除)時,zookeeper會通知客戶端。
1、客戶端啟動時向zookeeper服務(wù)器注冊信息
2、客戶端啟動同時注冊一系列的Watcher類型的監(jiān)聽器到本地的WatchManager中
3、zookeeper服務(wù)器中節(jié)點(diǎn)發(fā)生變化后,觸發(fā)watcher事件后通知給客戶端,客戶端線程從WatcherManager中取出對應(yīng)的Watcher對象來執(zhí)行回調(diào)邏輯。
zookeeper監(jiān)聽的事件類型
EventType.NodeCreated:當(dāng)znode節(jié)點(diǎn)被創(chuàng)建時,該事件被觸發(fā)。
EventType.NodeChildrenChanged:當(dāng)znode節(jié)點(diǎn)的直接子節(jié)點(diǎn)被創(chuàng)建、被刪除、子節(jié)點(diǎn)數(shù)據(jù)發(fā)生變更時,該事件被觸發(fā)。
EventType.NodeDataChanged:當(dāng)znode節(jié)點(diǎn)的數(shù)據(jù)發(fā)生變更時,該事件被觸發(fā)。
EventType.NodeDeleted:當(dāng)znode節(jié)點(diǎn)被刪除時,該事件被觸發(fā)。
EventType.None:當(dāng)zookeeper客戶端的連接狀態(tài)發(fā)生變更時,即KeeperState.Expired、KeeperState.Disconnected、KeeperState.SyncConnected、KeeperState.AuthFailed狀態(tài)切換時,描述的事件類型為EventType.None。
zookeeper下server工作狀態(tài)
LOOKING:當(dāng)前server不知道leader是誰,正在選舉
LEADING:當(dāng)前server即為選舉出來的leader
FOLLOWING:leader已經(jīng)選舉出來,當(dāng)前server是follower
?ZAB協(xié)議
ZAB 協(xié)議全稱:Zookeeper Atomic Broadcast(Zookeeper 原子廣播協(xié)議)。
ZAB 協(xié)議作用:解決分布式數(shù)據(jù)管理一致性。
ZAB 協(xié)議定義:ZAB 協(xié)議是為分布式協(xié)調(diào)服務(wù) Zookeeper 專門設(shè)計的一種支持 崩潰恢復(fù) 和 消息廣播 協(xié)議。
基于該協(xié)議,Zookeeper 實(shí)現(xiàn)了一種 主備模式 的系統(tǒng)架構(gòu)來保持集群中各個副本之間數(shù)據(jù)一致性。
消息廣播
zookeeper集群采用主從(leader-follower)模式保證服務(wù)高可用。leader節(jié)點(diǎn)可讀可寫,follower節(jié)點(diǎn)只讀,這種模式就需要保證leader節(jié)點(diǎn)和follower節(jié)點(diǎn)的數(shù)據(jù)一致性。對于客戶端發(fā)送的寫請求,全部由 Leader 接收,Leader 將請求封裝成一個事務(wù) Proposal,將其發(fā)送給所有 Follwer ,然后,根據(jù)所有 Follwer 的反饋,如果超過半數(shù)成功響應(yīng),則執(zhí)行 commit 操作(先提交自己,再發(fā)送 commit 給所有 Follwer)。
注:上述中有一個概念:兩階段提交過程(分布式系統(tǒng)中數(shù)據(jù)一致性經(jīng)常會涉及到的方案)。follower節(jié)點(diǎn)是可以處理寫請求的,會轉(zhuǎn)發(fā)給leader節(jié)點(diǎn)。leader節(jié)點(diǎn)通過消息廣播(二階段提交)同步寫操作到follower節(jié)點(diǎn),保證數(shù)據(jù)一致性。
zookeeper中每個事務(wù)都對應(yīng)一個ZXID(全局的、唯一的、順序的)。ZXID 是一個 64 位的數(shù)字,其中低 32 位可以看作是一個簡單的遞增的計數(shù)器,針對客戶端的每一個事務(wù)請求,Leader 都會產(chǎn)生一個新的事務(wù) Proposal 并對該計數(shù)器進(jìn)行 + 1 操作。而高 32 位則代表了 Leader 服務(wù)器上取出本地日志中最大事務(wù) Proposal 的 ZXID,并從該 ZXID 中解析出對應(yīng)的 epoch 值,然后再對這個值加一。
崩潰恢復(fù)
即如果在消息廣播的過程中,leader死掉了,如何保證數(shù)據(jù)的一致性問題。
假設(shè)兩種異常情況:
1、一個事務(wù)在 Leader 上提交了,并且過半的 Folower 都響應(yīng) Ack 了,但是 Leader 在 Commit 消息發(fā)出之前掛了。
2、假設(shè)一個事務(wù)在 Leader 提出之后,Leader 掛了。
考慮到上述兩種異常情況,Zab 協(xié)議崩潰恢復(fù)要求滿足以下兩個要求:
1)確保已經(jīng)被 Leader 提交的 Proposal 必須最終被所有的 Follower 服務(wù)器提交。
2)確保丟棄已經(jīng)被 Leader 提出的但是沒有被提交的 Proposal。
崩潰恢復(fù)主要包含:leader選舉 和 數(shù)據(jù)恢復(fù)。
leader選舉:
1、要求?可用節(jié)點(diǎn)數(shù)量 > 總節(jié)點(diǎn)數(shù)量/2??。注意 是 > , 不是 ≥。
? ? 2、新選舉出來的 Leader 不能包含未提交的 Proposal(新選舉的 Leader 必須都是已經(jīng)提交了 Proposal 的 Follower 服務(wù)器節(jié)點(diǎn)) 、新選舉的 Leader 節(jié)點(diǎn)中含有最大的 zxid(可以避免 Leader 服務(wù)器檢查 Proposal 的提交和丟棄工作。如果zxid相同,選擇server_id【zoo.cfg中的myid】最大的。)
數(shù)據(jù)恢復(fù):
1、上面講過了ZXID的高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事務(wù)的唯一性。同時,也能讓 Follwer 通過高 32 位識別不同的 Leader。簡化了數(shù)據(jù)恢復(fù)流程。
2、基于這樣的策略:當(dāng) Follower 鏈接上 Leader 之后,Leader 服務(wù)器會根據(jù)自己服務(wù)器上最后被提交的 ZXID 和 Follower 上的 ZXID 進(jìn)行比對,比對結(jié)果要么回滾,要么和 Leader 同步。
zookeeper集群腦裂
集群的腦裂通常是發(fā)生在節(jié)點(diǎn)之間通信不可達(dá)的情況下,集群會分裂成不同的小集群,小集群各自選出自己的master節(jié)點(diǎn),導(dǎo)致原有的集群出現(xiàn)多個master節(jié)點(diǎn)的情況。
zookeeper集群節(jié)點(diǎn)數(shù)(奇數(shù)or偶數(shù)?)
只要我們清楚集群leader選舉的要求(可用節(jié)點(diǎn)數(shù)量 > 總節(jié)點(diǎn)數(shù)量/2? 。注意 是 > , 不是 ≥),我相信很容易明白奇數(shù)節(jié)點(diǎn)集群相比偶數(shù)節(jié)點(diǎn)的集群有更大的優(yōu)勢。
1、發(fā)生腦裂(分成2個小集群)的情況下,奇數(shù)節(jié)點(diǎn)的集群總會有一個小集群滿足可用節(jié)點(diǎn)數(shù)量 > 總節(jié)點(diǎn)數(shù)量/2,所以zookeeper集群總能選取出leader。
2、在容錯能力相同的情況下,奇數(shù)集群更節(jié)省資源。還是要清楚leader選舉的要求哈,舉個列子:3個節(jié)點(diǎn)的集群,如果集群可以正常工作(即leader選舉成功),至少需要2個節(jié)點(diǎn)是正常的;4個節(jié)點(diǎn)的集群,如果集群可以正常工作(即leader選舉成功),至少需要3個節(jié)點(diǎn)是正常的。那么3個節(jié)點(diǎn)的集群和4個節(jié)點(diǎn)的集群都有一個節(jié)點(diǎn)宕機(jī)的容錯能力。很明顯,在容錯能力相同的情況下,奇數(shù)節(jié)點(diǎn)的集群更節(jié)省資源。
?zookeeper和eureka對比
在分布式系統(tǒng)領(lǐng)域有個著名的 CAP定理(C- 數(shù)據(jù)一致性;A-服務(wù)可用性;P-服務(wù)對網(wǎng)絡(luò)分區(qū)故障的容錯性,這三個特性在任何分布式系統(tǒng)中不能同時滿足,最多同時滿足兩個)。
zookeeper基于CP,即任何時刻對ZooKeeper的訪問請求能得到一致的數(shù)據(jù)結(jié)果,同時系統(tǒng)對網(wǎng)絡(luò)分割具備容錯性;但是它不能保證每次服務(wù)請求的可用性(注:也就 是在極端環(huán)境下,zookeeper可能會丟棄一些請求,消費(fèi)者程序需要重新請求才能獲得結(jié)果)。至于zookeeper為啥不能保證服務(wù)的高可用,大家可以想一下發(fā)生腦裂后無法選取leader、選取leader過程中丟棄某些請求。當(dāng)網(wǎng)絡(luò)出現(xiàn)故障時,剩余zk集群server會發(fā)起投票選舉新的leader,但是此過程會持續(xù)30~120s,此過程對于高并發(fā)來說十分漫長,會導(dǎo)致整個注冊服務(wù)的癱瘓,這是不可容忍的。?
Eureka基于AP,不會有類似于ZooKeeper的選舉leader的過程,采用的是Peer to Peer 對等通信,沒有l(wèi)eader/follower的說法,每個peer都是對等的;客戶端請求會自動切換 到新的Eureka節(jié)點(diǎn);當(dāng)宕機(jī)的服務(wù)器重新恢復(fù)后,Eureka會再次將其納入到服務(wù)器集群管理之中。當(dāng)Eureka節(jié)點(diǎn)接受客戶端請求時,所有的操作都會在節(jié)點(diǎn)間進(jìn)行復(fù)制(replicate To Peer)操作,將請求復(fù)制到該 Eureka Server 當(dāng)前所知的其它所有節(jié)點(diǎn)中。至于為啥Eureka不能保證數(shù)據(jù)一致性,源于Eureka的自我保護(hù)機(jī)制:如果在15分鐘內(nèi)超過85%的節(jié)點(diǎn)都沒有正常的心跳,那么Eureka就認(rèn)為客戶端與注冊中心出現(xiàn)了網(wǎng)絡(luò)故障,此時會出現(xiàn)以下幾種情況:?
1. Eureka不再從注冊列表中移除因?yàn)殚L時間沒收到心跳而應(yīng)該過期的服務(wù) 。
2. Eureka仍然能夠接受新服務(wù)的注冊和查詢請求,但是不會被同步到其它節(jié)點(diǎn)上(即保證當(dāng)前節(jié)點(diǎn)依然可用) 。
3. 當(dāng)網(wǎng)絡(luò)穩(wěn)定時,當(dāng)前實(shí)例新的注冊信息會被同步到其它節(jié)點(diǎn)中。
因此, Eureka可以很好的應(yīng)對因網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點(diǎn)失去聯(lián)系的情況,而不會像zookeeper那樣使整個注冊服務(wù)癱瘓。
總結(jié)
以上是對zookeeper的工作原理和相關(guān)概念的一些整理,希望能對大家認(rèn)識zookeeper有所幫助。下一篇文章開始基于zookeeper做一個簡單的分布式配置中心,敬請期待!!!
參考鏈接
https://blog.csdn.net/pml18710973036/article/details/64121522
https://www.cnblogs.com/stateis0/p/9062133.html
https://www.jianshu.com/p/2bceacd60b8a
?
轉(zhuǎn)載于:https://www.cnblogs.com/hujunzheng/p/10887937.html
總結(jié)
以上是生活随笔為你收集整理的基于zookeeper实现分布式配置中心(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国美易卡申请码怎么用
- 下一篇: 红箭-8L反坦克导弹