1. 程式人生 > >15年老架構師總結為什麼我們需要Zookeeper?

15年老架構師總結為什麼我們需要Zookeeper?

為什麼需要分散式系統 單機系統已經無法滿足業務需要 高效能硬體價格昂貴

分散式系統帶來哪些問題 叢集中節點資料一致性問題 叢集產生分割槽 負載問題 冪等性問題 可用性問題 Session問題

分散式PAC設計原則 一個經典的分散式系統理論。CAP理論告訴我們:一個分散式系統不可能同時滿足一致性(C:Consistency)、可用性(A:Availability)和分割槽容錯性(P:Partition tolerance)這三個基本需求,最多隻能同時滿足其中兩項。

1、一致性

在分散式環境下,一致性是指資料在多個副本之間能否保持一致的特性。在一致性的需求下,當一個系統在資料一致的狀態下執行更新操作後,應該保證系統的資料仍然處於一致的狀態。

對於一個將資料副本分佈在不同分散式節點上的系統來說,如果對第一個節點的資料進 行了更新操作並且更新成功後,卻沒有使得第二個節點上的資料得到相應的更新,於是在對第二個節點的資料進行讀取操作時,獲取的依然是老資料(或稱為髒數 據),這就是典型的分散式資料不一致的情況。在分散式系統中,如果能夠做到針對一個數據項的更新操作執行成功後,所有的使用者都可以讀取到其最新的值,那麼 這樣的系統就被認為具有強一致性

2、可用性

可用性是指系統提供的服務必須一直處於可用的狀態,對於使用者的每一個操作請求總是能夠在有限的時間內返回結果。這裡的重點是"有限時間內"和"返回結果"。

"有限時間內"是指,對於使用者的一個操作請求,系統必須能夠在指定的時間內返回對 應的處理結果,如果超過了這個時間範圍,那麼系統就被認為是不可用的。另外,"有限的時間內"是指系統設計之初就設計好的執行指標,通常不同系統之間有很 大的不同,無論如何,對於使用者請求,系統必須存在一個合理的響應時間,否則使用者便會對系統感到失望。

"返回結果"是可用性的另一個非常重要的指標,它要求系統在完成對使用者請求的處理後,返回一個正常的響應結果。正常的響應結果通常能夠明確地反映出隊請求的處理結果,即成功或失敗,而不是一個讓使用者感到困惑的返回結果。

3、分割槽容錯性

分割槽容錯性約束了一個分散式系統具有如下特性:分散式系統在遇到任何網路分割槽故障的時候,仍然需要能夠保證對外提供滿足一致性和可用性的服務,除非是整個網路環境都發生了故障。

網路分割槽是指在分散式系統中,不同的節點分佈在不同的子網路(機房或異地網路) 中,由於一些特殊的原因導致這些子網路出現網路不連通的狀況,但各個子網路的內部網路是正常的,從而導致整個系統的網路環境被切分成了若干個孤立的區域。 需要注意的是,組成一個分散式系統的每個節點的加入與退出都可以看作是一個特殊的網路分割槽。

既然一個分散式系統無法同時滿足一致性、可用性、分割槽容錯性三個特點,所以我們就需要拋棄一樣:

Paxos如何解決分散式一致問題 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的基本思路,對照ZooKeeper,對應關係就是: 團員 -client 議員 -server 議員的筆記本 -server中的資料 提案 -變更資料的請求 提案編號 -zxid(ZooKeeper Transaction Id) 提案生效 -執行變更資料的操作 ZooKeeper中還有一個leader的概念,就是把發起提案的權利收緊了,以前是每個議員都可以發起提案,現在有了leader,大家就不要七嘴八舌了,先把提案都交給leader,由leader一個個發起提案 Paxos演算法就是通過投票、全域性編號機制,使同一時刻只有一個寫操作被批准,同時併發的寫操作要去爭取選票,只有獲得過半數選票的寫操作才會被批准,所以永遠只會有一個寫操作得到批准,其他的寫操作競爭失敗只好再發起一輪投票

zookeeper特性介紹 一致性保證: 更新請求順序進行,來自同一個client的更新請求按其傳送順序依次執行 資料更新原子性,一次資料更新要麼成功,要麼失敗 全域性唯一資料檢視,client無論連線到哪個server,資料檢視都是一致的 實時性,在一定事件範圍內,client能讀到最新資料

zookeeper選舉流程

1.選舉執行緒由當前Server發起選舉的執行緒擔任,其主要功能是對投票結果進行統計,並選出推薦的Server;

2.選舉執行緒首先向所有Server發起一次詢問(包括自己);

3.選舉執行緒收到回覆後,驗證是否是自己發起的詢問(驗證zxid是否一致),然後獲取對方的id(myid),並存儲到當前詢問物件列表中,最後獲取對方提議的leader相關資訊(id,zxid),並將這些資訊儲存到當次選舉的投票記錄表中;

4.收到所有Server回覆以後,就計算出zxid最大的那個Server,並將這個Server相關資訊設定成下一次要投票的Server;

5.執行緒將當前zxid最大的Server設定為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數,設定當前推薦的leader為獲勝的Server,將根據獲勝的Server相關資訊設定自己的狀態,否則,繼續這個過程,直到leader被選舉出來

zookeeper讀寫流程 寫流程 客戶端連線到叢集中某一個節點 客戶端傳送寫請求 服務端連線節點,把該寫請求轉發給leader leader處理寫請求,一半以上的從節點也寫成功,返回給客戶端成功。

讀流程 客戶端連線到叢集中某一節點 讀請求,直接返回。

zookeeper儲存策略 持久化儲存是基於記憶體快照(snapshot)和事務日誌(txlog)來儲存。 snapshot和txlog的儲存目錄定義在zoo.cfg中,txlog儲存磁碟和snapshot儲存磁碟分開,避免io爭奪。 txlog的刷盤閾值是1000。txlog是生成snapshot之後生成。 snapshot的儲存數量和清理時間間隔配置在zoo.cfg中。 zookeeper 使用concurrenthashmap進行儲存。鎖的粒度是segment,減少鎖競爭,segment裡對應一個hashtable 的若干桶. 所以時間複雜度都是 O(1)

zookeeper應用場景 資料釋出與訂閱

釋出與訂閱即所謂的配置管理,顧名思義就是將資料釋出到zk節點上,供訂閱者動態獲取資料,實現配置資訊的集中式管理和動態更新。例如全域性的配置資訊,地址列表等就非常適合使用。

  1. 索引資訊和叢集中機器節點狀態存放在zk的一些指定節點,供各個客戶端訂閱使用。

  2. 系統日誌(經過處理後的)儲存,這些日誌通常2-3天后被清除。

  3. 應用中用到的一些配置資訊集中管理,在應用啟動的時候主動來獲取一次,並且在節點上註冊一個Watcher,以後每次配置有更新,實時通知到應用,獲取最新配置資訊。

  4. 業務邏輯中需要用到的一些全域性變數,比如一些訊息中介軟體的訊息佇列通常有個offset,這個offset存放在zk上,這樣叢集中每個傳送者都能知道當前的傳送進度。

  5. 系統中有些資訊需要動態獲取,並且還會存在人工手動去修改這個資訊。以前通常是暴露出介面,例如JMX介面,有了zk後,只要將這些資訊存放到zk節點上即可。

分佈通知/協調

ZooKeeper 中特有watcher註冊與非同步通知機制,能夠很好的實現分散式環境下不同系統之間的通知與協調,實現對資料變更的實時處理。使用方法通常是不同系統都對 ZK上同一個znode進行註冊,監聽znode的變化(包括znode本身內容及子節點的),其中一個系統update了znode,那麼另一個系統能 夠收到通知,並作出相應處理。

  1. 另一種心跳檢測機制:檢測系統和被檢測系統之間並不直接關聯起來,而是通過zk上某個節點關聯,大大減少系統耦合。

  2. 另一種系統排程模式:某系統有控制檯和推送系統兩部分組成,控制檯的職責是控制推送系統進行相應的推送工作。管理人員在控制檯作的一些操作,實際上是修改 了ZK上某些節點的狀態,而zk就把這些變化通知給他們註冊Watcher的客戶端,即推送系統,於是,作出相應的推送任務。

  3. 另一種工作彙報模式:一些類似於任務分發系統,子任務啟動後,到zk來註冊一個臨時節點,並且定時將自己的進度進行彙報(將進度寫回這個臨時節點),這樣任務管理者就能夠實時知道任務進度。

總之,使用zookeeper來進行分散式通知和協調能夠大大降低系統之間的耦合。

分散式鎖

分散式鎖,這個主要得益於ZooKeeper為我們保證了資料的強一致性,即使用者只要完全相信每時每刻,zk叢集中任意節點(一個zk server)上的相同znode的資料是一定是相同的。鎖服務可以分為兩類,一個是保持獨佔,另一個是控制時序。 保持獨佔,就是所有試圖來獲取這個鎖的客戶端,最終只有一個可以成功獲得這把鎖。通常的做法是把zk上的一個znode看作是一把鎖,通過create znode的方式來實現。所有客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。 控制時序,就是所有檢視來獲取這個鎖的客戶端,最終都是會被安排執行,只是有個全域性時序了。做法和上面基本類似,只是這裡 /distribute_lock 已經預先存在,客戶端在它下面建立臨時有序節點(這個可以通過節點的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)。Zk的父節點(/distribute_lock)維持一份sequence,保證子節點建立的時序性,從而也形成了每個客戶端的全域性時序。

叢集管理

  1. 叢集機器監控:這通常用於那種對叢集中機器狀態,機器線上率有較高要求的場景,能夠快速對叢集中機器變化作出響應。這樣的場景中,往往有一個監控系統,實時檢測叢集機器是否存活。過去的做法通常是:監控系統通過某種手段(比如ping)定時檢測每個機器,或者每個機器自己定時向監控系統彙報“我還活著”。 這種做法可行,但是存在兩個比較明顯的問題:1. 叢集中機器有變動的時候,牽連修改的東西比較多。2. 有一定的延時。

利用ZooKeeper有兩個特性,就可以實時另一種叢集機器存活性監控系統:a. 客戶端在節點 x 上註冊一個Watcher,那麼如果 x 的子節點變化了,會通知該客戶端。b. 建立EPHEMERAL型別的節點,一旦客戶端和伺服器的會話結束或過期,那麼該節點就會消失。

  1. Master選舉則是zookeeper中最為經典的使用場景了。 在分散式環境中,相同的業務應用分佈在不同的機器上,有些業務邏輯(例如一些耗時的計算,網路I/O處理),往往只需要讓整個叢集中的某一臺機器進行執行, 其餘機器可以共享這個結果,這樣可以大大減少重複勞動,提高效能,於是這個master選舉便是這種場景下的碰到的主要問題。 利用ZooKeeper的強一致性,能夠保證在分散式高併發情況下節點建立的全域性唯一性,即:同時有多個客戶端請求建立 /currentMaster 節點,最終一定只有一個客戶端請求能夠建立成功。

zookeeper虛擬機器安裝 略