zookeeper淺談

1、ZooKeeper是什麼?

ZooKeeper 是一個開源的分散式服務框架Hadoop的一個子專案,Zookeeper 實現諸如資料釋出/訂閱、統一命名服務、分散式協調/通知、配置管理、分散式鎖和分散式佇列等功能,通俗的講zookeeper是一個支援增刪查改的類似檔案系統特點的資料庫,按照規則去給節點分配任務。zookeeper底層實現了儲存檔案和通知回撥功能它的資料結構類似於一個標準的檔案系統,相比較檔案系統zk的每個節點都可以儲存資料,但是大小限制為1M。通常我們在使用dubbo的時候會建議使用zookeeper作為註冊中心,也可以用redis,eureka作為註冊中心,當然我只用過zookeeper,dubbo相當於搭載一個服務框架,zookeeper則是服務註冊的中心。

zookeeper淺談

zk的資料結構

zookeeper淺談

zk服務的配置檔案

上面提到zk就是一個數據庫那麼它的資料就儲存在dataDir中,上圖中的配置是一個叢集配置,有server1,server2,server3三臺伺服器,我們這裡是一個偽叢集(同一臺機器啟動三個server),我們可以看到localhost:A:B,其中licalhost是我們的服務ip,A是專門用來選舉的埠,B叢集進行通訊埠,clientPort是對client提供服務的埠。

名詞解釋:

資料釋出/訂閱:

初始化節點的時候在服務節點註冊一個數據變更Watcher ,對節點進行變更操作的時候會將資料通知到客戶端,客戶端接受到變更通知後會重新讀取變更後的資料。

統一命名服務:

獲得全域性的唯一名稱,還可以藉助znode順序節點的特性產生的節點都會返回順序編號,在按照給定的名字,生成具有特殊含義的統一名字,所有客戶端可建立同一個名字的不同順序節點。

2、伺服器的角色?以及狀態

伺服器有Leader、Follower、Observer三種角色 ,其中Leader是叢集內部各個服務的排程者,保證了事務處理的順序性。Follower參與Proposal的投票,參與Leader選舉投票,處理客戶端的非事務請求,轉發事務請求(增刪改,資料變更的操作)給Leader伺服器。Observer不參與投票,在不參與叢集事務能力的基礎上提升叢集的非事務處理能力。

伺服器的狀態分別為LOOKING(認為進群中伺服器沒有Leader尋找Leader的狀態)、FOLLOWING(伺服器角色是Follower的狀態)、LEADING(伺服器角色是 Leader的狀)、OBSERVING(伺服器角色是Observer的狀態)。

領導者選舉發生的節點有Leader掛掉的時候,叢集伺服器啟動的時候,Follower掛掉後Leader發現沒有過半的Follower跟隨了,這三種情況會觸發領導者選舉。

3、zookeeper如何解決資料一致性問題?

zookeeper server的啟動過程經歷了什麼。

若要了解zookeepr如何解決資料一致性,zookeeper其實想達到的是強一致性,但是最終達到的是最終一致性,首先我們瞭解下什麼是CAP?這個大家自行百度,ZK遵循的是CP原則,犧牲了可用性,滿足了強一致性。如下圖資料庫A 的資料進行了變更為2後,在步驟2進行讀取的時候不能讀取到的是1,那麼要求資料庫之間同步非常迅速或者在步驟2上加上鎖待資料同步完成後再讀取到結果。

zookeeper淺談

強一致性的例子

我們來大致跟下原始碼中的選舉流程我用的是git上的3。6。1的版本,找到zkServer。sh

zookeeper淺談

找到守護程序的啟動指令碼

找到引數中ZOOMAIN=“org。apache。zookeeper。server。quorum。QuorumPeerMain”對應的這個類就是你檢視原始碼服務的入口了。

在入口main方法中有一個初始化方法,main。initializeAndRun(args);這個方法進入以後圖中標紅的是進入叢集模式的方法,我們來看這個方法。

zookeeper淺談

判斷為叢集模式

進入方法之後你會看到一堆set,讀取配置檔案值到QuorumPeer這個物件中呢,然後是物件的start,在啟動的時候就進行了呼叫選舉方法。

大家想一下zookeeper為何選擇奇數伺服器?

這個要從zookeeper的過半機制說起,假如6臺機器只最大允許叢集中宕掉2臺機器,5 臺機器也是允許宕機兩臺,從資源利用的角度所以建議選擇奇數臺伺服器。

zookeeper淺談

標紅的這塊為//投票決定方式,預設超過半數就透過

zookeeper淺談

標紅的為leader選舉方法

zookeeper淺談

預設electionAlgorithm為3

在FastLeaderElection類中lookForLeader方法的case looking 條件下進行投票選舉。private boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch)將收到的對方的投票與當前自己的投票對比,判斷對方的投票是否優於自己的投票。

zookeeper淺談

totalOrderPredicate

只要當前伺服器狀態為LOOKING,進入迴圈,不斷地讀取其它Server發來的通知、進行比較、更新自己的投票、傳送自己的投票、統計投票結果,直到leader選出或出錯退出。

選舉比重引數

①Serverid:伺服器ID比如有三臺伺服器,編號分別是1,2,3。編號越大在選擇演算法中的權重越大。

②Zxid:事務日誌id,事務請求每次就會生成一條事務日誌,伺服器中存放的最大資料ID。值越大說明資料越新,在選舉演算法中資料越新權重越大。

③Epoch:邏輯時鐘,或者叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個資料就會增加,然後與接收到的其它伺服器返回的投票資訊中的數值相比

叢集啟動投票流程

①每個Server會發出一個投票,因此對於Server1,Server2和Server3來說,都會將自己作為Leader伺服器來進行投票,每次投票包含最基本的元素有:所推舉的伺服器的myid和zxid,我們以(myid,zxid)的形式來表示,即Server1的投票為(1,0),Server2的投票為(2,0),然後各自將這個投票發給叢集中其他所有機器。

② 接收來自各個伺服器的投票,判斷該投票的有效性,包括檢查是否是本輪投票,是否來自LOOKING狀態的伺服器。

③ pk投票,在接收到來自其他伺服器的投票後,針對每一個投票,伺服器都需要將別人的投票和自己的投票進行PK:

優先檢查zxid,zxid比較大的伺服器優先作為Leader。

如果zxid相同的話,那麼就比較myid,myid比較大的伺服器作為Leader伺服器。結果Server1{(2,0),(2,0)},Server2{(2,0),2,0)}將票投給了Server2,那麼Server3也就直接跟隨投給了Sever2,最終確定了Leader。

作者:宜信技術學院 王巧敏