ZooKeeper

分佈式系統

A distributed system is de ned as a software system that is composed of independent computing entities linked together by a computer network whose components communicate and coordinate with each other to achieve a common goal.
分佈式系統是由獨立的計算機經過網絡鏈接在一塊兒,而且經過一些組件來相互交流和協做來完成一個共同的目標。

分佈式系統特性

  • 資源共享,例如存儲空間,計算能力,數據,和服務等等
  • 擴展性,從軟件和硬件上增長系統的規模
  • 併發性,多個用戶同時訪問
  • 性能,確保當負載增長的時候,系統想要時間不會有影響
  • 容錯性,儘管一些組件暫時不可用了,整個系統仍然是可用的
  • API抽象,系統的獨立組件對用戶隱藏,僅僅暴露服務

ZooKeeper

Zookeeper是一個分佈式開源框架,提供了協調分佈式應用的基本服務,它向外部應用暴露一組通用服務——分佈式同步(Distributed Synchronization)、命名服務(Naming Service)、集羣維護(Group Maintenance)等,簡化分佈式應用協調及其管理的難度,提供高性能的分佈式服務。ZooKeeper自己能夠以單機模式安裝運行,不過它的長處在於經過分佈式ZooKeeper集羣(一個Leader,多個Follower),基於必定的策略來保證ZooKeeper集羣的穩定性和可用性,從而實現分佈式應用的可靠性。
一、Zookeeper是爲別的分佈式程序服務的
二、Zookeeper自己就是一個分佈式程序(只要有半數以上節點存活,zk就能正常服務)
三、Zookeeper所提供的服務涵蓋:主從協調、服務器節點動態上下線、統一配置管理、分佈式共享鎖、統一名稱服務等
四、雖說能夠提供各類服務,可是zookeeper在底層其實只提供了兩個功能:node

  • 管理(存儲,讀取)用戶程序提交的數據(相似namenode中存放的metadata)
  • 併爲用戶程序提供數據節點監聽服務;

Zookeeper特性

  • Zookeeper:一個leader,多個follower組成的集羣
  • 全局數據一致:每一個server保存一份相同的數據副本,client不管鏈接到哪一個server,數據都是一致的
  • 分佈式讀寫,更新請求轉發,由leader實施
  • 更新請求順序進行,來自同一個client的更新請求按其發送順序依次執行
  • 數據更新原子性,一次數據更新要麼成功,要麼失敗
  • 實時性,在必定時間範圍內,client能讀到最新數據

Zookeeper數據結構

  • 層次化的目錄結構,命名符合常規文件系統規範(相似文件系統)

clipboard.png

  • 每一個節點在zookeeper中叫作znode,而且其有一個惟一的路徑標識
  • 節點Znode能夠包含數據和子節點(可是EPHEMERAL類型的節點不能有子節點)

Zookeeper節點類型

  • 短暫(ephemeral)(create -e /app1/test1 「test1」 客戶端斷開鏈接zk刪除ephemeral類型節點)
  • 持久(persistent) (create -s /app1/test2 「test2」 客戶端斷開鏈接zk不刪除persistent類型節點)

Znode目錄節點

  • PERSISTENT
  • PERSISTENT_SEQUENTIAL(持久序列/test0000000019 )
  • EPHEMERAL
  • EPHEMERAL_SEQUENTIAL
    (默認是persistent )

建立znode時設置順序標識,znode名稱後會附加一個值,順序號是一個單調遞增的計數器,由父節點維護;在分佈式系統中,順序號能夠被用於爲全部的事件進行全局排序,這樣客戶端能夠經過順序號推斷事件的順序服務器

Zookeeper應用場景

數據發佈與訂閱(配置中心)

發佈與訂閱模型,即所謂的配置中心,顧名思義就是發佈者將數據發佈到ZK節點上,供訂閱者動態獲取數據,實現配置信息的集中式管理和動態更新。例如全局的配置信息,服務式服務框架的服務地址列表等就很是適合使用。網絡

負載均衡

這裏說的負載均衡是指軟負載均衡。在分佈式環境中,爲了保證高可用性,一般同一個應用或同一個服務的提供方都會部署多份,達到對等服務。而消費者就需要在這些對等的服務器中選擇一個來執行相關的業務邏輯,其中比較典型的是消息中間件中的生產者,消費者負載均衡。
消息中間件中發佈者和訂閱者的負載均衡,linkedin開源的KafkaMQ和阿里開源的 metaq都是經過zookeeper來作到生產者、消費者的負載均衡。這裏以metaq爲例如講下:
生產者負載均衡:metaq發送消息的時候,生產者在發送消息的時候必須選擇一臺broker上的一個分區來發送消息,所以metaq在運行過程當中,會把全部broker和對應的分區信息所有註冊到ZK指定節點上,默認的策略是一個依次輪詢的過程,生產者在經過ZK獲取分區列表以後,會按照brokerId和partition的順序排列組織成一個有序的分區列表,發送的時候按照從頭至尾循環往復的方式選擇一個分區來發送消息。
消費負載均衡: 在消費過程當中,一個消費者會消費一個或多個分區中的消息,可是一個分區只會由一個消費者來消費。MetaQ的消費策略是:session

  1. 每一個分區針對同一個group只掛載一個消費者。
  2. 若是同一個group的消費者數目大於分區數目,則多出來的消費者將不參與消費。
  3. 若是同一個group的消費者數目小於分區數目,則有部分消費者須要額外承擔消費任務。

在某個消費者故障或者重啓等狀況下,其餘消費者會感知到這一變化(經過 zookeeper watch消費者列表),而後從新進行負載均衡,保證全部的分區都有消費者進行消費。數據結構

命名服務(Naming Service)

命名服務也是分佈式系統中比較常見的一類場景。在分佈式系統中,經過使用命名服務,客戶端應用可以根據指定名字來獲取資源或服務的地址,提供者等信息。被命名的實體一般能夠是集羣中的機器,提供的服務地址,遠程對象等等——這些咱們均可以統稱他們爲名字(Name)。其中較爲常見的就是一些分佈式服務框架中的服務地址列表。經過調用ZK提供的建立節點的API,可以很容易建立一個全局惟一的path,這個path就能夠做爲一個名稱。
阿里巴巴集團開源的分佈式服務框架Dubbo中使用ZooKeeper來做爲其命名服務,維護全局的服務地址列表, 點擊這裏查看Dubbo開源項目。在Dubbo實現中:
服務提供者在啓動的時候,向ZK上的指定節點/dubbo/${serviceName}/providers目錄下寫入本身的URL地址,這個操做就完成了服務的發佈。
服務消費者啓動的時候,訂閱/dubbo/${serviceName}/providers目錄下的提供者URL地址, 並向/dubbo/${serviceName} /consumers目錄下寫入本身的URL地址。
注意,全部向ZK上註冊的地址都是臨時節點,這樣就可以保證服務提供者和消費者可以自動感應資源的變化。 另外,Dubbo還有針對服務粒度的監控,方法是訂閱/dubbo/${serviceName}目錄下全部提供者和消費者的信息。併發

分佈式通知/協調

ZooKeeper中特有watcher註冊與異步通知機制,可以很好的實現分佈式環境下不一樣系統之間的通知與協調,實現對數據變動的實時處理。使用方法一般是不一樣系統都對ZK上同一個znode進行註冊,監聽znode的變化(包括znode自己內容及子節點的),其中一個系統update了znode,那麼另外一個系統可以收到通知,並做出相應處理app

  1. 另外一種心跳檢測機制:檢測系統和被檢測系統之間並不直接關聯起來,而是經過zk上某個節點關聯,大大減小系統耦合。
  2. 另外一種系統調度模式:某系統有控制檯和推送系統兩部分組成,控制檯的職責是控制推送系統進行相應的推送工做。管理人員在控制檯做的一些操做,其實是修改了ZK上某些節點的狀態,而ZK就把這些變化通知給他們註冊Watcher的客戶端,即推送系統,因而,做出相應的推送任務。
  3. 另外一種工做彙報模式:一些相似於任務分發系統,子任務啓動後,到zk來註冊一個臨時節點,而且定時將本身的進度進行彙報(將進度寫回這個臨時節點),這樣任務管理者就可以實時知道任務進度。

總之,使用zookeeper來進行分佈式通知和協調可以大大下降系統之間的耦合負載均衡

集羣管理與Master選舉

1.集羣機器監控:這一般用於那種對集羣中機器狀態,機器在線率有較高要求的場景,可以快速對集羣中機器變化做出響應。這樣的場景中,每每有一個監控系統,實時檢測集羣機器是否存活。過去的作法一般是:監控系統經過某種手段(好比ping)定時檢測每一個機器,或者每一個機器本身定時向監控系統彙報「我還活着」。 這種作法可行,可是存在兩個比較明顯的問題:框架

  • 集羣中機器有變更的時候,牽連修改的東西比較多。
  • 有必定的延時。

利用ZooKeeper有兩個特性,就能夠實現另外一種集羣機器存活性監控系統:異步

  • 客戶端在節點 x 上註冊一個Watcher,那麼若是 x的子節點變化了,會通知該客戶端。
  • 建立EPHEMERAL類型的節點,一旦客戶端和服務器的會話結束或過時,那麼該節點就會消失。

例如,監控系統在 /clusterServers 節點上註冊一個Watcher,之後每動態加機器,那麼就往 /clusterServers 下建立一個 EPHEMERAL類型的節點:/clusterServers/{hostname}. 這樣,監控系統就可以實時知道機器的增減狀況,至於後續處理就是監控系統的業務了。
2.Master選舉則是zookeeper中最爲經典的應用場景了。
在分佈式環境中,相同的業務應用分佈在不一樣的機器上,有些業務邏輯(例如一些耗時的計算,網絡I/O處理),每每只須要讓整個集羣中的某一臺機器進行執行,其他機器能夠共享這個結果,這樣能夠大大減小重複勞動,提升性能,因而這個master選舉即是這種場景下的碰到的主要問題。
利用ZooKeeper的強一致性,可以保證在分佈式高併發狀況下節點建立的全局惟一性,即:同時有多個客戶端請求建立 /currentMaster 節點,最終必定只有一個客戶端請求可以建立成功。利用這個特性,就能很輕易的在分佈式環境中進行集羣選取了。
另外,這種場景演化一下,就是動態Master選舉。這就要用到EPHEMERAL_SEQUENTIAL類型節點的特性了。
上文中提到,全部客戶端建立請求,最終只有一個可以建立成功。在這裏稍微變化下,就是容許全部請求都可以建立成功,可是得有個建立順序,因而全部的請求最終在ZK上建立結果的一種可能狀況是這樣: /currentMaster/{sessionId}-1 ,/currentMaster/{sessionId}-2,/currentMaster/{sessionId}-3 ….. 每次選取序列號最小的那個機器做爲Master,若是這個機器掛了,因爲他建立的節點會立刻小時,那麼以後最小的那個機器就是Master了。

  • 在搜索系統中,若是集羣中每一個機器都生成一份全量索引,不只耗時,並且不能保證彼此之間索引數據一致。所以讓集羣中的Master來進行全量索引的生成,而後同步到集羣中其它機器。另外,Master選舉的容災措施是,能夠隨時進行手動指定master,就是說應用在zk在沒法獲取master信息時,能夠經過好比http方式,向一個地方獲取master。
  • 在Hbase中,也是使用ZooKeeper來實現動態HMaster的選舉。在Hbase實現中,會在ZK上存儲一些ROOT表的地址和HMaster的地址,HRegionServer也會把本身以臨時節點(Ephemeral)的方式註冊到Zookeeper中,使得HMaster能夠隨時感知到各個HRegionServer的存活狀態,同時,一旦HMaster出現問題,會從新選舉出一個HMaster來運行,從而避免了HMaster的單點問題

分佈式鎖

分佈式鎖,這個主要得益於 ZooKeeper 爲咱們保證了數據的強一致性。鎖服務能夠分爲兩類,一個是 保持獨佔,另外一個是 控制時序。

  1. 所謂保持獨佔,就是全部試圖來獲取這個鎖的客戶端,最終只有一個能夠成功得到這把鎖。一般的作法是把 zk 上的一個 znode 看做是一把鎖,經過 create znode 的方式來實現。全部客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。
  2. 控制時序,就是全部視圖來獲取這個鎖的客戶端,最終都是會被安排執行,只是有個全局時序了。作法和上面基本相似,只是這裏 /distributelock 已經預先存在,客戶端在它下面建立臨時有序節點(這個能夠經過節點的屬性控制:CreateMode.EPHEMERALSEQUENTIAL 來指定)。Zk 的父節點(/distribute_lock)維持一份 sequence, 保證子節點建立的時序性,從而也造成了每一個客戶端的全局時序。
相關文章
相關標籤/搜索