高級程序員知識學習(zookeeper相關知識)

Zookeeper基礎知識

Zookeeper 是一個分佈式協調服務,可用於服務發現,分佈式鎖,分佈式領導選舉,配置管理等。Zookeeper 提供了一個類似於 Linux 文件系統的樹形結構(可認爲是輕量級的內存文件系統,但只適合存少量信息,完全不適合存儲大量文件或者大文件),同時提供了對於每個節點的監控與通知機制。

Zookeeper是一個分佈式的服務的一個框架,主要是用於解決分佈式應用的中經常遇見大問題:例如:同意命名、集羣服務、分佈式應用配置等。Zookeeper是一個數據庫也是一個文件系統特點的數據庫,爲了解決一致性問題的分佈式數據庫,具有訂閱和發佈功能的分佈式數據庫(watch 機制)。

Leader: 1一個 Zookeeper 集羣同一時間只會有一個實際工作的 Leader,它會發起並維護與各 Follwer及 Observer 間的心跳。2. 所有的寫操作必須要通過 Leader 完成再由 Leader 將寫操作廣播給其它服務器。 只要有超過半數節點(不包括 observeer 節點) 寫入成功,該寫請求就會被提交(類 2PC 協議)

Follower: 1. 一個 Zookeeper 集羣可能同時存在多個 Follower,它會響應 Leader 的心跳,2. Follower 可直接處理並返回客戶端的讀請求,同時會將寫請求轉發給 Leader 處理,

3. 並且負責在 Leader 處理寫請求時對請求進行投票。

Observer: 角色與 Follower 類似,但是無投票權。 Zookeeper 需保證高可用和強一致性,爲了支持更多的客戶端,需要增加更多 Server; Server 增多,投票階段延遲增大,影響性能; 引入 Observer,Observer 不參與投票; Observers 接受客戶端的連接,並將寫請求轉發給 leader 節點; 加入更多 Observer 節點,提高伸縮性,同時不影響吞吐率。

Zookeeper的數據一致性

Consistency 是一致性(強一致性) Availity 可用性 Partition tolerant 分區容錯性CAP 是不能同時滿足的,是因爲這個理論是由網絡來保證分區容錯性。所以在不能同時滿足。Zookeeper 的核心是原子廣播機制,這個機制保證了各個 server 之間的同步。實現這個機制的協議叫做 Zab 協議。Zab 協議有兩種模式,它們分別是恢復模式和廣播模式。

恢復模式

當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數 server 完成了和 leader 的狀態同步以後,恢復模式就結束了。狀態同步保證了 leader 和 server 具有相同的系統狀態。

廣播模式

一旦 leader 已經和多數的 follower 進行了狀態同步後,它就可以開始廣播消息了,即進入廣播狀態。這時候當一server加入 ZooKeeper 服務中,它會在恢復模式下啓動,發現 leader,並和 leader 進行狀態同步。待到同步結束,它也參與消息廣播。ZooKeeper 服務一直維持在 Broadcast 狀態,直到 leader 崩潰了或者leader 失去了大部分的 followers 支持。

Zookeeper Watcher 機制

Zookeeper 允許客戶端向服務端的某個 Znode 註冊一個 Watcher 監聽,當服務端的一些指定事件觸發了這個 Watcher,服務端會向指定客戶端發送一個事件通知來實現分佈式的通知功能,然後客戶端根據 Watcher 通知狀態和事件類型做出業務上的改變。

工作機制:

(1)客戶端註冊 watcher

(2)服務端處理 watcher

(3)客戶端回調 watcher

Watcher 特性總結:

(1)一次性

無論是服務端還是客戶端,一旦一個 Watcher 被 觸 發 ,Zookeeper 都會將其從相應的存儲中移除。這樣的設計有效的減輕了服務端的壓力,不然對於更新非常頻繁的節點,服務端會不斷的向客戶端發送事件通知,無論對於網絡還是服務端的壓力都非常大。

(2)客戶端串行執行

客戶端 Watcher 回調的過程是一個串行同步的過程。

(3)輕量

3.1、Watcher 通知非常簡單,只會告訴客戶端發生了事件,而不會說明事件的具體內容。

3.2、客戶端向服務端註冊 Watcher 的時候,並不會把客戶端真實的 Watcher 對象實體傳遞到服務端,僅僅是在客戶端請求中使用 boolean 類型屬性進行了標記。

(4)watcher event 異步發送 watcher 的通知事件從 server 發送到 client 是異步的,這就存在一個問題,不同的客戶端和服務器之間通過 socket 進行通信,由於網絡延遲或其他因素導致客戶端在不通的時刻監聽到事件,由於 Zookeeper 本身提供了 ordering guarantee,即客戶端監聽事件後,纔會感知它所監視 znode發生了變化。所以我們使用 Zookeeper 不能期望能夠監控到節點每次的變化。Zookeeper 只能保證最終的一致性,而無法保證強一致性。

(5)註冊 watcher getData、exists、getChildren

(6)觸發 watcher create、delete、setData

(7)當一個客戶端連接到一個新的服務器上時,watch 將會被以任意會話事件觸發。當與一個服務器失去連接的時候,是無法接收到 watch 的。而當 client 重新連接時,如果需要的話,所有先前註冊過的 watch,都會被重新註冊。通常這是完全透明的。只有在一個特殊情況下,watch 可能會丟失:對於一個未創建的 znode的 exist watch,如果在客戶端斷開連接期間被創建了,並且隨後在客戶端連接上之前又刪除了,這種情況下,這個 watch 事件可能會被丟失。

客戶端註冊 Watcher 實現

(1)調用 getData()/getChildren()/exist()三個 API,傳入 Watcher 對象

(2)標記請求 request,封裝 Watcher 到 WatchRegistration

(3)封裝成 Packet 對象,發服務端發送 request

(4)收到服務端響應後,將 Watcher 註冊到 ZKWatcherManager 中進行管理

(5)請求返回,完成註冊。

服務端處理 Watcher 實現

(1)服務端接收 Watcher 並存儲

接收到客戶端請求,處理請求判斷是否需要註冊 Watcher,需要的話將數據節點的節點路徑和 ServerCnxn(ServerCnxn 代表一個客戶端和服務端的連接,實現了 Watcher 的 process 接口,此時可以看成一個 Watcher 對象)存儲在WatcherManager 的 WatchTable 和 watch2Paths 中去。

(2)Watcher 觸發

以服務端接收到 setData() 事務請求觸發 NodeDataChanged 事件爲例:

2.1 封裝 WatchedEvent

將通知狀態(SyncConnected)、事件類型(NodeDataChanged)以及節點路徑封裝成一個 WatchedEvent 對象

2.2 查詢 Watcher

從 WatchTable 中根據節點路徑查找 Watcher

2.3 沒找到;說明沒有客戶端在該數據節點上註冊過 Watcher

2.4 找到;提取並從 WatchTable 和 Watch2Paths 中刪除對應 Watcher(從這裏可以看出 Watcher 在服務端是一次性的,觸發一次就失效了)

(3)調用 process 方法來觸發 Watcher

這裏 process 主要就是通過 ServerCnxn 對應的 TCP 連接發送 Watcher 事件通知。

9. 客戶端回調 Watcher

客戶端 SendThread 線程接收事件通知,交由 EventThread 線程回調 Watcher。

客戶端的 Watcher 機制同樣是一次性的,一旦被觸發後,該 Watcher 就失效了。

Zookeeper中的分佈式鎖原理

zookeeper 是如何保證事務的順序一致性的?

zookeeper 採用全局遞增的事務 Id 來標識,所有的 proposal(提議)都在被提出的時候加上了 zxid,zxid 實際上是一個 64 位的數字,高 32 位是 epoch( 時期; 紀元; 世; 新時代)用來標識 leader 週期,如果有新的 leader 產生出來,epoch會自增,低 32 位用來遞增計數。當新產生 proposal 的時候,會依據數據庫的兩階段過程,首先會向其他的server 發出事務執行請求,超過半數的機器都能執行並且能夠成功,那麼就會開始執行。

Zookeeper 分佈式鎖(文件系統、通知機制)

有了 zookeeper 的一致性文件系統,鎖的問題變得容易。鎖服務可以分爲兩類,一個是保持獨佔,另一個是控制時序。

對於第一類,我們將 zookeeper 上的一個 znode 看作是一把鎖,通過 createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。用完刪除掉自己創建的 distribute_lock 節點就釋放出鎖。

對於第二類, /distribute_lock 已經預先存在,所有客戶端在它下面創建臨時順序編號目錄節點,和選 master 一樣,編號最小的獲得鎖,用完刪除,依次方便。

Zookeeper 隊列管理(文件系統、通知機制)

兩種類型的隊列:

(1)同步隊列,當一個隊列的成員都聚齊時,這個隊列纔可用,否則一直等待所有成員到達。

(2)隊列按照 FIFO 方式進行入隊和出隊操作。

第一類,在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。

第二類,和分佈式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。在特定的目錄下創建 PERSISTENT_SEQUENTIAL 節點,創建成功時Watcher 通知等待的隊列,隊列刪除序列號最小的節點用以消費。此場景下Zookeeper 的 znode 用於消息存儲,znode 存儲的數據就是消息隊列中的消息內容,SEQUENTIAL 序列號就是消息的編號,按序取出即可。由於創建的節點是持久化的,所以不必擔心隊列消息的丟失問題。

Zookeeper的集羣高原理

ZAB的協議包括以下的內容:集羣中的服務怎麼選舉?數據的怎麼樣進行兩階段的提交。數據的怎麼的實現的數據的同步?

ZXID:全局事務的ID.

在 ZAB ( ZooKeeper Atomic Broadcast , ZooKeeper 原子消息廣播協議) 協議的事務編號 Zxid設計中, Zxid 是一個 64 位的數字,其中低 32 位是一個簡單的單調遞增的計數器, 針對客戶端每一個事務請求,計數器加 1;而高 32 位則代表 Leader 週期 epoch 的編號, 每個當選產生一個新的 Leader 服務器,就會從這個 Leader 服務器上取出其本地日誌中最大事務的 ZXID,並從中讀取epoch 值,然後加 1,以此作爲新的 epoch,並將低 32 位從 0 開始計數。Zxid(Transaction id) 類似於 RDBMS 中的事務 ID,用於標識一次更新操作的 Proposal(提議)ID。爲了保證順序性,該 zkid 必須單調遞增。

Epoch: 集羣所處的年代或者週期

epoch:可以理解爲當前集羣所處的年代或者週期,每個 leader 就像皇帝,都有自己的年號,所以每次改朝換代,leader 變更之後,都會在前一個年代的基礎上加 1。這樣就算舊的 leader 崩潰恢復之後,也沒有人聽他的了,因爲 follower 只聽從當前年代的 leader 的命令。

Zab 協議有兩種模式-恢復模式(選主)、廣播模式(同步)

Zab 協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步) 。當服務啓動或者在領導者崩潰後, Zab 就進入了恢復模式,當領導者被選舉出來,且大多數 Server 完成了和 leader 的狀態同步以後,恢復模式就結束了。狀態同步保證了 leader 和 Server 具有相同的系統狀態。

ZAB 協議 4 階段

Leader election(選舉階段-選出準 Leader)

1. Leader election(選舉階段) : 節點在一開始都處於選舉階段,只要有一個節點得到超半數節點的票數,它就可以當選準 leader。只有到達 廣播階段(broadcast) 準 leader 纔會成爲真正的 leader。這一階段的目的是就是爲了選出一個準 leader,進入下一個階段。

Discovery(發現階段-接受議、生成 epoch、接受 epoch)

2. Discovery(發現階段) : 在這個階段, followers 跟準 leader 進行通信,同步 followers最近接收的事務提議。這個一階段的主要目的是發現當前大多數節點接收的最新提議,並且準 leader 生成新的 epoch,讓 followers 接受,更新它們的 accepted Epoch一個 follower 只會連接一個 leader, 如果有一個節點 f 認爲另一個 follower p 是 leader, f在嘗試連接 p 時會被拒絕, f 被拒絕之後,就會進入重新選舉階段。

Synchronization(同步階段-同步 follower 副本)

3. Synchronization(同步階段) : 同步階段主要是利用 leader前一階段獲得的最新提議歷史,同步集羣中所有的副本。 只有當 大多數節點都同步完成,準 leader 纔會成爲真正的 leader。follower 只會接收 zxid 比自己的 lastZxid 大的提議。

Broadcast(廣播階段-leader 消息廣播)

4. Broadcast(廣播階段) : 到了這個階段, Zookeeper 集羣才能正式對外提供事務服務,並且 leader 可以進行消息廣播。同時如果有新的節點加入,還需要對新節點進行同步。ZAB 提交事務並不像 2PC 一樣需要全部 follower 都 ACK, 只需要得到超過半數的節點的 ACK 就可以了。

Zookeeper的投票機制

 

1領導:領導者的選取機制

2預提交(詢問) ack   兩階段的提交

3過半機制

在leader的選舉的過程中是不能夠提供服務的,

具體的投票的流程如下:

每個 sever 首先給自己投票, 然後用自己的選票和其他 sever 選票對比, 權重大的勝出,使用權重較大的更新自身選票箱。 具體選舉過程如下:

1. 每個 Server 啓動以後都詢問其它的 Server 它要投票給誰。對於其他 server 的詢問,

server 每次根據自己的狀態都回復自己推薦的 leader 的 id 和上一次處理事務的 zxid(系

統啓動時每個 server 都會推薦自己)

2. 收到所有 Server 回覆以後,就計算出 zxid 最大的哪個 Server,並將這個 Server 相關信息設置成下一次要投票的 Server。

3. 計算這過程中獲得票數最多的的 sever 爲獲勝者,如果獲勝者的票數超過半數,則改

server 被選爲 leader。否則,繼續這個過程,直到 leader 被選舉出來

4. leader 就會開始等待 server 連接

5. Follower 連接 leader,將最大的 zxid 發送給 leader

6. Leader 根據 follower 的 zxid 確定同步點,至此選舉階段完成。

7. 選舉階段完成 Leader 同步後通知 follower 已經成爲 uptodate 狀態

8. Follower 收到 uptodate 消息後,又可以重新接受 client 的請求進行服務了13/04/2018

zk 節點宕機如何處理?

Zookeeper 本身也是集羣,推薦配置不少於 3 個服務器。Zookeeper 自身也要保證當一個節點宕機時,其他節點會繼續提供服務。

如果是一個 Follower 宕機,還有 2 臺服務器提供訪問,因爲 Zookeeper 上的數據是有多個副本的,數據並不會丟失;

如果是一個 Leader 宕機,Zookeeper 會選舉出新的 Leader。

ZK 集羣的機制是隻要超過半數的節點正常,集羣就能正常提供服務。只有在 ZK節點掛得太多,只剩一半或不到一半節點能工作,集羣才失效。所以3 個節點的 cluster 可以掛掉 1 個節點(leader 可以得到 2 票>1.5)2 個節點的 cluster 就不能掛掉任何 1 個節點了(leader 可以得到 1 票<=1)

Zookeeper的面試問題

 

zookeeper 負載均衡和 nginx 負載均衡區別

zk 的負載均衡是可以調控,nginx 只是能調權重,其他需要可控的都需要自己寫插件;但是 nginx 的吞吐量比 zk 大很多,應該說按業務選擇用哪種方式。

Zookeeper 和 Dubbo 的關係?

Zookeeper的作用:

zookeeper用來註冊服務和進行負載均衡,哪一個服務由哪一個機器來提供必需讓調用者知道,簡單來說就是ip地址和服務名稱的對應關係。當然也可以通過硬編碼的方式把這種對應關係在調用方業務代碼中實現,但是如果提供服務的機器掛掉調用者無法知曉,如果不更改代碼會繼續請求掛掉的機器提供服務。zookeeper通過心跳機制可以檢測掛掉的機器並將掛掉機器的ip和服務對應關係從列表中刪除。至於支持高併發,簡單來說就是橫向擴展,在不更改代碼的情況通過添加機器來提高運算能力。通過添加新的機器向zookeeper註冊服務,服務的提供者多了能服務的客戶就多了。

dubbo:

是管理中間層的工具,在業務層到數據倉庫間有非常多服務的接入和服務提供者需要調度,dubbo提供一個框架解決這個問題。

注意這裏的dubbo只是一個框架,至於你架子上放什麼是完全取決於你的,就像一個汽車骨架,你需要配你的輪子引擎。這個框架中要完成調度必須要有一個分佈式的註冊中心,儲存所有服務的元數據,你可以用zk,也可以用別的,只是大家都用zk。

zookeeper和dubbo的關係:

Dubbo 的將註冊中心進行抽象,它可以外接不同的存儲媒介給註冊中心提供服務,有 ZooKeeper,Memcached,Redis 等。

引入了 ZooKeeper 作爲存儲媒介,也就把 ZooKeeper 的特性引進來。首先是負載均衡,單註冊中心的承載能力是有限的,在流量達到一定程度的時 候就需要分流,負載均衡就是爲了分流而存在的,一個 ZooKeeper 羣配合相應的 Web 應用就可以很容易達到負載均衡;資源同步,單單有負載均衡還不 夠,節點之間的數據和資源需要同步,ZooKeeper 集羣就天然具備有這樣的功能;命名服務,將樹狀結構用於維護全局的服務地址列表,服務提供者在啓動 的時候,向 ZooKeeper 上的指定節點 /dubbo/${serviceName}/providers 目錄下寫入自己的 URL 地址,這個操作就完成了服務的發佈。 其他特性還有 Mast 選舉,分佈式鎖等。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章