前言
zookeeper本質上就是一個分佈式協調服務,用來解決分佈式一致性的問題。java
本文適合有必定分佈式基礎的讀者閱讀。什麼叫相關的基礎呢?起碼你得知道系統架構爲什麼從集中式演變成了分佈式,分佈式有哪些優勢和問題。基於分佈式的問題,適當的學習下CAP,知道分佈式面臨了什麼的問題以及如何根據業務特色在C(一致性)和A(可用性)之間尋求平衡。以後學習下e-bay的架構師提出的BASE理論,BASE是CAP中一致性和可用性權衡的結果,來源於大規模互聯網分佈式系統的總結,其核心思想是使服務在一個基本可用的狀態下,根據業務的特色使用適當的方式使系統達到最終一致性。在對一個分佈式系統進行架構設計中,每每會在系統的可用性和一致性作權衡,瞭解一下經典的分佈式一致性協議也是極好的。好比著名的2pc、3pc、以及paxos協議,明白各自的優缺點。mysql
若是你對上述部份內容感到很是陌生,尤爲是關於CPA和BASE的理論知識都不太清楚的話,最好先補一下相關的基礎,由於這是指導全部分佈式架構理論的基石。這裏推薦一本書能夠系統的學習分佈式理論和zookeeper,本人對於zookeeper的學習大部分也是基於此書《從Paxos到Zookeeper分佈式一致性原理與實踐》.redis
友情提示:本文是對《從Paxos到Zookeeper分佈式一致性原理與實踐》的一個簡單總結,方便做者本人也就是我本身日常翻閱看,快速過一下zookeeper的各個點。若是你讀起來有點吃力,徹底不知所云且對zookeeper又有一絲絲興趣,那麼老老實實看書吧~。算法
初識zookeeper
zookeeper的應用場景
- 數據發佈/訂閱
數據發佈/訂閱系統,即所謂的配置中心,其實就是發佈者將數據發佈到Zookeeper上,供訂閱者進行數據訂閱,利用watcher機制進行動態獲取數據的目的,實現分佈式架構中配置信息的集中管理和數據的動態更新。百度開源的disconf就是典型這種場景的實現。
- 註冊中心
阿里巴巴開源的框架dubbo相信大部分人都多多少少的有些瞭解,它是一個致力於提供高性能和透明化的遠程服務調用方案和基於服務框架展開的完整SOA服務治理方案。在這,咱們主要聊下dubbo中基於zookeeper實現的服務註冊中心。註冊中心是RPC框架中最核心的模塊之一,用於服務的註冊和訂閱。假設如今有一個應用,提供了一個rpc服務com.bin.IBinService。服務提供者在初始化啓動時,會在zookeeper集羣中對應的目錄下/dubbo/com.bin.IBinSerivce/providers節點下建立一個子節點,並寫入本身的URL地址,這就表明了IBinService這個服務的一個提供者,如有多個服務提供者,同理zookeeper也會生成多個子節點。服務消費者會在zookeeper的/dubbo/com.bin.IBinSerivce/consumers節點下建立一個臨時節點,並寫入本身的url地址,這就表明了這個服務的一個消費者。dubbo做爲一個完成的soa服務治理框架,也提供了集羣容錯和軟負載的功能,都是從zookeeper上拉取全部的提供者,根據設置的策略進行。
- Master選舉
master選舉是一個在分佈式系統中很是常見的應用場景。接下來,咱們重點看master選舉的過程。在集羣的全部機器中選出一臺機器做爲master,針對這個需求,咱們能夠選擇常見的關係型數據庫的主鍵特性來實現:集羣中全部機器向數據庫中插入一條相同主鍵ID的記錄,數據庫會幫助咱們保證主鍵的惟一性和衝突檢查,也就是說成功的那臺機器將成爲master。但這個方案的致命缺點就是若是當前的master掛了,怎麼處理?顯然數據庫無法通知咱們這個事件,咱們能夠經過zookeeper垂手可得的作到這一點。利用zookeeper的強一致性,可以很好地保證在分佈式高併發環境下節點的建立必定可以保證全局惟一性。若是有多個客戶端同時建立同一個節點,那麼最終必定只有一個客戶端可以請求建立成功。利用這個特性,就能夠很容易的在分佈式環境進行Master選舉了。假如master掛了,如何根據zookeeper進行動態master選舉呢?集羣中全部機器都會向zookeeper定時建立一個臨時節點(/master_election/2018/leader),只有一臺機器可以成功建立這個節點,那麼這臺機器就成爲了master。同時其餘沒有建立成功的機器都會在節點(/master_election/2018)上註冊一個子節點變動的watcher,用於監控當前的master機器是否存活,一旦發現當前的master掛了,那麼其他的機器將會進行Master選舉.
- 分佈式鎖
常見的分佈式鎖有三種實現方式,基於mysql,redis和zookeeper的。分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式。在一般的java開發編程中,有兩種常見的鎖,分別是synchronized機制和JDK5提供的ReentranLock。zookeeper是使用了一個數據節點來表示爲一個鎖。在須要去獲取鎖時,全部的客戶端都會去建立一個節點,好比:/exclusive_lock/lock,zookeeper會保證只有一個客戶端可以建立成功,,那麼就認爲該客戶端獲取了鎖。同時其餘全部沒有得到到鎖的客戶端就須要到/exclusive_lock節點下注冊一個子節點變動的watcher監聽,以便實時監聽到lock節點消失,通知其餘客戶端去從新建立節點得到分佈式鎖。
常見的應用場景已經講完了,或許你有些迷迷糊糊,以爲太理論了,我想要看代碼。其實基礎理論知識若是懂了,代碼是很簡單的。這裏給你們推薦一個好用的客戶端,Netflix公司開源的一套zookeeper客戶端框架:Curator。它是目前全世界範圍內使用最普遍的zookeeper客戶端。它處理了許多很是底層的細節工做,包括鏈接重連、反覆註冊watcher和各類ZNODE異常,而且它還提供了zookeeper各類應用場景(Recipe,master選舉和共享鎖)的抽象封裝。若是你想看zookeeper自己是怎麼實現的,那你就看zookeeper原生客戶端。若是你想要使用zookeeperAPI,那必定首選Curator。數據庫
zookeeper的一些細節
- 數據模型
zookeeper的視圖結構與unix文件系統很是相似,但他沒有引入傳統文件系統中目錄和文件的概念,而是使用了特有的數據節點ZNode。ZNode是zookeeper中數據最小單元,每一個ZNode上均可以保存數據,同時還能夠掛載子節點,所以造成了一棵樹。

- 節點特性
在zookeeper中,每一個數據節點都是有生命週期的。整體可分爲三類:持久節點(PERSISTENT),臨時節點(EPHEMERAL)和順序節點(SEQUENTIAL),具體在使用過程當中。能夠生成四種組合類型:持久節點、持久順序節點、臨時節點、臨時順序節點。
持久節點:zookeeper最多見的節點類型。一旦被建立後,就會一直存在zookeeper服務器上,直到有操做來主動清除這個節點。
持久順序節點:相對於持久節點,它額外的特性表如今順序性上。在zookeeper中,每一個父節點都會爲它的第一級子節點維護一份順序,用於記錄下節點被建立的前後順序。基於這個特性,在建立子節點的時候,能夠設置這個標記,生成的節點名稱就會添加一個數字後綴做爲新的節點名。值得注意的是數字後綴的上限是整型的最大值。
臨時節點:它的生命週期和客戶端的會話綁定在一塊兒,也就是說,若是客戶端會話失效,這個節點會被自動清除。zookeeper規定了不能基於臨時節點來建立子節點,也就是子節點只能成爲葉子節點。
臨時順序節點:和臨時節點同樣,也是多出了順序的特性。
- Watcher
一個典型的發佈訂閱系統定義了一種一對多的訂閱關係,可以讓多個訂閱者同時監聽某一個主題對象,當這個主題對象自身狀態變化時,會通知全部訂閱者,使他們能作出相應的處理。zookeeper中使用了watcher機制來實現這種分佈式的通知功能。zookeeper容許客戶端向服務端註冊一個watcher監聽,當服務端的 一些指定事件觸發了這個Watcher,那麼就會像指定的客戶端發送一個事件通知來實現分佈式的通知功能。整個流程以下圖所示:
- 服務期間的角色介紹 在zookeeper集羣中,分別有leader、follwer和observer三種類型的服務器角色。 leader:它是整個zookeeper集羣中工做的核心,它是事務請求的惟一調度和處理者,保證集羣事務處理的順序性,同事它也是集羣內部各服務器的調度者。 follwer:follwer服務器是zookeeper集羣狀態的跟隨者,其主要工做有:處理客戶端非事務請求,轉發事務請求給leader服務器,參與事務請求的proposal的投票,參與leader選舉投票 observer:observer服務器充當了一個觀察者的角色,它會觀察zookeeper最新的集羣狀態並同步過來。它的工做原理和follwer基本上是同樣的,對於非事務請求均可以進行獨立的處理,對於非事務請求,會轉發給leader服務器進行處理。和follwer惟一的區別就是,不參與事務請求proposal和leadr選舉的投票。簡單的說,observer只提供非事務服務,用於不影響集羣事務處理能力的前提下提高集羣地非事務處理能力。