溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

二、zookeeper--基本原理

發(fā)布時間:2020-07-22 23:30:29 來源:網絡 閱讀:619 作者:隔壁小白 欄目:大數據

一、概述

1、基本概述

Zookeeper是一個開源的分布式的,為分布式應用提供協(xié)調服務的Apache項目。Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致服務的軟件。


2、zk提供了什么

雖然可以用zk實現很多功能,但是實際上zk只提供了三個東西:文件系統(tǒng)、通知機制、集群管理機制。

(1)文件系統(tǒng)

zk的存儲的數據的結構,類似于一個文件系統(tǒng),結構如下: 二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖1.1 zk文件系統(tǒng)

每個節(jié)點稱為znode,每個znode都是一個類似于KV的結構,每個節(jié)點名稱相當于key,每個節(jié)點中都保存了對應的數據,類似于Key對應的value。每個znode下面都可以有多個子節(jié)點,就這樣一直延續(xù)下去,構成了類似于Linux文件系統(tǒng)的架構。

(2)通知機制

當某個client監(jiān)聽某個節(jié)點時(watch機制,后面有講),當該節(jié)點發(fā)生變化時(有可能是增加子節(jié)點,或者節(jié)點值變了等),zk就會通知監(jiān)聽該節(jié)點的客戶端。后續(xù)該怎么處理就看客戶端的處理邏輯了。

(3)集群管理機制

zk本身是一個集群結構,有一個leader節(jié)點,負責寫請求,多個follower負責響應讀請求。并且在leader節(jié)點故障時,會自動根據選舉機制從剩下的follower中選出新的leader。


3、特點

1)Zookeeper:一個領導者(leader),多個跟隨者(follower)組成的集群。 2)Leader負責進行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)。 3)Follower用于接收客戶請求并向客戶端返回結果,在選舉Leader過程中參與投票。 4)集群中奇數臺服務器只要有半數以上節(jié)點存活,Zookeeper集群就能正常服務。 5)全局數據一致:每個server保存一份相同的數據副本,client無論連接到哪個server,數據都是一致的。 6)更新請求順序進行,來自同一個client的更新請求按其發(fā)送順序依次執(zhí)行。 7)數據更新原子姓,一次數據更新要么成功,要么失敗。 8)實時姓,在一定時間范圍內,client能讀到最新數據。


二、zk中的概念和原理

1、zk中節(jié)點的角色分類

leader: 1.恢復數據; 2.維持與Learner的心跳,接收Learner請求并判斷Learner的請求消息類型; 3.Learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據不同的消息類型,進行不同的處理。 PING消息是指Learner的心跳信息;REQUEST消息是Follower發(fā)送的提議信息,包括寫請求及同步請求;ACK消息是Follower的對提議的回復,超過半數的Follower通過,則commit該提議;REVALIDATE消息是用來延長SESSION有效時間。

follower: 1)向Leader發(fā)送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);| 2)接收Leader消息并進行處理; 3)接收Client的請求,如果為寫請求,發(fā)送給Leader進行處理; 4)返回Client結果。

Follower的消息循環(huán)處理如下幾種來自Leader的消息: 1)PING消息:心跳消息 2)PROPOSAL消息:Leader發(fā)起的提案,要求Follower投票 3)COMMIT消息:服務器端最新一次提案的信息 4)UPTODATE消息:表明同步完成 5)REVALIDATE消息:根據Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受消息 6)SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發(fā)起,用來強制得到最新的更新。

observer:和follower類似,但是不參與投票和選舉 learner:follower和observer的統(tǒng)稱

2、zk中節(jié)點的類型

短暫節(jié)點--ephemeral: 客戶端和服務器端斷開連接后,創(chuàng)建的節(jié)點自己刪除。并且在還未斷開的過程中,這個臨時的節(jié)點對其他客戶端來說都是可見的。其中也可以分為普通的短暫節(jié)點和帶序號的短暫節(jié)點。帶序號的短暫節(jié)點稱為ephemeral_sequential,就是會在節(jié)點的名稱最后加上一串序號,標明順序

持久節(jié)點--persistent: 創(chuàng)建的節(jié)點會永久存在,即使客戶端和服務器端斷開連接。也分為普通和帶序號,區(qū)別和上面類似


3、zk選舉leader原理

首先先說幾個相關概念: zxid: 每次修改zk中的數據以及zk的狀態(tài)的變化(比如發(fā)生過選舉等),就會有一個zxid數字串,每次隨著事務的增加,會逐漸遞增。所以zxid小的事務肯定最先發(fā)生的。

myid(sid): 每個zk節(jié)點服務器編號,在配置文件中指定的,必須保證全局唯一。

zk的幾個狀態(tài): looking--表示正在搜尋leader leading--當前正在選舉leader following--leader選舉出來之后,正在新的leader和follower之間同步數據 observing:observer正在接受選舉結果

下面正式講選舉過程: leader的選舉基于paxos算法實現,這里不細究算法原理,就簡單講講選舉的過程。 (1)第一輪投票:所有活的zk節(jié)點都會將票投給自己,并將選票結果廣播給其他節(jié)點。因為這個時候也不知道其他節(jié)點的情況,選票上有兩個關鍵信息:當前節(jié)點最新的zxid以及sid。zxid越大,表示該節(jié)點所擁有的數據越新,所以zxid大的節(jié)點是會被首先選舉成leader的;如果zxid相同,則比較sid,sid大的選舉為leader。且因為sid是全局唯一的,所以根據這個原則,一定可以選出唯一的leader。 (2)收到其他節(jié)點的投票后,獲取選票中的zxid以及sid,根據(1)的比較原則,選擇最新的,然后更新選票,再把新的選票發(fā)送出去,并將選票標記為“第二輪選票”。我們要注意,因為每個節(jié)點收到其他節(jié)點的選票的時間點一般是不一致的,不同的節(jié)點會有延遲,所以會導致有不同選舉輪次的選票出現。所以當節(jié)點發(fā)現自己的收到的選票比自己當前的投出的選票輪次大時,那么就直接更新當前選票,然后投出去。并且每個節(jié)點都會進行選票的歸檔統(tǒng)計(同一輪次的選票),如果發(fā)現沒有節(jié)點選票過半數,節(jié)點就繼續(xù)將最新的(zxix,sid)選票投出。 (3)在經歷了多次(2)流程后,如果節(jié)點歸檔選票后,發(fā)現有節(jié)點選票過半,就會停止投票。而如果節(jié)點發(fā)現歸檔統(tǒng)計的結果,發(fā)現leader就是自己的話,就會廣播告訴其他節(jié)點,我是leader。 (4)其他節(jié)點收到新的leader消息后,就會開始leader和follower的數據同步。


4、節(jié)點的元信息stat

當我們使用stat path或者get path的方式查看節(jié)點元信息時,會有很多信息項目,那么每一項表示什么呢?

1)czxid- 引起這個znode創(chuàng)建的zxid,創(chuàng)建節(jié)點的事務的zxid 每次修改ZooKeeper狀態(tài)都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。 事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前發(fā)生。 2)ctime - znode被創(chuàng)建的毫秒數(從1970年開始) 3)mzxid - znode最后更新的zxid 4)mtime - znode最后修改的毫秒數(從1970年開始) 5)pZxid-znode最后更新的子節(jié)點zxid 6)cversion - znode子節(jié)點變化號,znode子節(jié)點修改次數 7)dataversion - znode數據變化號 8)aclVersion - znode訪問控制列表的變化號 9)ephemeralOwner- 如果是臨時節(jié)點,這個是znode擁有者的session id。如果不是臨時節(jié)點則是0。 10)dataLength- znode的數據長度 11)numChildren - znode子節(jié)點數量


5、zk寫流程

二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖 2.1 zk寫數據流程

讀是局部姓的,即client只需要從與它相連的follower上讀取數據即可; 寫請求時,follower會將請求轉發(fā)給leader,leader通過transaction(事務)的形式廣播執(zhí)行,這個過程是怎樣的呢? (1)leader 會給所有follower發(fā)送一個PROPOSAL提案消息 (2)一個follower接收到這次PROPOSAL消息,寫到磁盤,發(fā)送給leader一個ACK消息,告知已經收到。 (3)當Leader收到法定人數(quorum)的follower的ACK時候,發(fā)送commit消息執(zhí)行。 注意:只有發(fā)送commit之后,做的修改才會提交,不然是會回退的;如果發(fā)現寫入超時,是會回退這個更新操作的。


6、監(jiān)聽器原理

1) 首先要有一個main()線程 2) 在main線程中創(chuàng)建ZK客戶端,這時會創(chuàng)建兩個線程,一個負責網絡連接通信(connect),一個負責監(jiān)聽(listener) 3) 通過connect線程將注冊的監(jiān)聽事件發(fā)送給ZK 4) 在ZK的注冊監(jiān)聽器列表中將注冊的監(jiān)聽事件添加到列表中 5) ZK監(jiān)聽到有數據或路徑發(fā)生變化時,就會將這個消息通過connect線程發(fā)送給listener線程 6) Listener線程內部調用process()方法

命令行下:客戶端使用類似 ls path watch 的方式來監(jiān)聽一個節(jié)點的子節(jié)點的變化 當節(jié)點的子節(jié)點發(fā)生變化時,會通知相應的客戶端,會顯示如下的信息:

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/

WatchedEvent state:SyncConnected---事件狀態(tài):同步更新
type:NodeChildrenChanged---類型:節(jié)點的子節(jié)點改變
path:/--路徑:/



三、應用場景

1、統(tǒng)一命名服務

二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖 3.1 zk統(tǒng)一命名服務

所謂命名服務就是對資源進行命名,用于更好地對資源進行定位。而zk本身的文件系統(tǒng)結構就可以創(chuàng)建以路徑為名稱的節(jié)點,用于存儲服務器地址等信息。并且每個節(jié)點的名稱都不會重復,嚴格按照文件系統(tǒng)的限制實現的。阿里巴巴開發(fā)的分布式服務框架DUBBO就是用zookeeper來作為其命名服務,維護全局的服務器列表,實現方式就是服務器啟動時,在ZK的某個路徑下創(chuàng)建一個代表自己的節(jié)點,節(jié)點的value存儲的就是對應服務的服務地址(比如說URL地址)。


2、統(tǒng)一配置管理

二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖 3.2 zk統(tǒng)一配置管理

在集群中環(huán)境的服務中,同一個程序會分布在多臺機器上運行,便于橫向擴展。個程序一般都會需要一些配置信息,如果程序分散部署在多臺機器上,要逐個改變配置就變得很困難。同時,目前各種分布式系統(tǒng)以及微服務的流行,如何有效管理不同組件的配置也是一項重要的問題?,F在可以在zk上創(chuàng)建一個節(jié)點,將配置信息作為節(jié)點的值。然后相關的應用程序都監(jiān)聽這個節(jié)點。當節(jié)點中的數據發(fā)生變化時,zk就會通知這些監(jiān)聽的程序說:“有東西改變了”。這些監(jiān)聽者就會自動到zk上獲取更改后的配置信息,接著后面如何處理就看具體的業(yè)務邏輯了。 其實這是用到了zk的watcher機制,也就是發(fā)布/訂閱機制,客戶端可以向zookeeper服務器注冊watcher,訂閱自己感興趣的節(jié)點,當相應的節(jié)點發(fā)生變化時,zookeeper服務器就會向客戶端發(fā)布通知。 類似的場景還會用在服務高可用中,比如有兩臺數據庫服務器,一主一備。 二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖3.3 zk統(tǒng)一配置管理--數據庫主備

其中主備的數據中都運行一個zk的監(jiān)控進程client,用于監(jiān)控數據庫服務的可用姓。當服務可用時,主備數據庫的client會和zk建立持久會話,向zk發(fā)送心跳信息,表示自己正常運行。zk收到心跳信息,就會在節(jié)點上創(chuàng)建相應的節(jié)點,節(jié)點數據為當前可用的主數據的地址(實際上沒有這么簡單,這里只是簡化了,便于理解)。如果任意一個數據庫服務下線了,那么對應的在zk上的節(jié)點也會被刪除。


3、服務動態(tài)上下線感知

二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖 3.4 zk服務動態(tài)上下線感知

對于一些復雜的分布式系統(tǒng)來說,系統(tǒng)中不同的組件非常多,即不同的服務很多。同一服務中還存在多臺并發(fā)處理的服務器。那么如何知道這些服務哪些是可用的,哪些是不可用的呢?這就得用到zk了。 當服務上線時,會創(chuàng)建zkclient,并和zk保持持久會話,然后在zk的特定特定目錄下創(chuàng)建一個臨時znode(會話一斷開,znode就消失)。而需要訪問這些服務的客戶端,就會監(jiān)聽在這個目錄下(watcher機制),通過 getChildren() 這個api監(jiān)聽。當目錄下的節(jié)點發(fā)生變化時,就意味著那些服務有下線或者上線了。這時候zk就會通知監(jiān)聽(訂閱)該節(jié)點的客戶端來獲取最新的可用的服務列表。這樣就可以動態(tài)上下線可用的服務。


4、統(tǒng)一集群管理

zk可以用于保存其他業(yè)務集群中每個節(jié)點的狀態(tài)信息,特別是一些主從結構的集群中。當發(fā)生故障轉移時,可以從zk獲取當前每個節(jié)點的狀態(tài)信息。典型的比如 HBase的master節(jié)點的選舉,就是通過zk協(xié)調狀態(tài)實現的。 集群每個節(jié)點會在對應的一個znode下創(chuàng)建自己對應的子znode,用于保存自己的狀態(tài)。然后每個節(jié)點都監(jiān)聽在這個znode下,也就是監(jiān)聽每個節(jié)點狀態(tài)的變化。正常情況下,如果一個集群不發(fā)生故障,zk中保存的所有節(jié)點信息是不會變化的。如果zk中發(fā)生變化,意味著集群有故障發(fā)生。后續(xù)集群可借助zk中的節(jié)點狀態(tài)數據來進行下一步的故障處理,比如選舉新的master等操作。


5、軟負載均衡

二、zookeeper--基本原理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖3.5 zk軟負載均衡

每個到服務列表下注冊的服務節(jié)點,相應的znode下的數據會保存服務地址,以及當前處理的訪問數。當客戶端來獲取服務列表時,可以根據訪問數選擇比較少的一個服務節(jié)點進行請求的分發(fā)。達到一定的負載均衡的作用。


6、分布式鎖

在一些資源的使用上,為了防止不同的請求的讀寫相互產生干擾,有了鎖的概念。比如并發(fā)情況下,購買一件限量的商品。為了保證商品的數量是安全的,就需要用到鎖機制。 鎖分為共享鎖(也叫讀鎖)和排他鎖(也叫寫鎖)。獲取共享鎖時,所有事務都可以對數據進行讀取,但是都不能修改數據。獲取排他鎖時,只有當前事務可以讀取和修改數據,其他事務不可以。 在分布式系統(tǒng)中,對某些資源的限制就必須采用分布式鎖,這種鎖比起傳統(tǒng)的非分布式鎖復雜。可以使用zk來實現,實現方式也很多,下面講一種。

首先,需要獲取鎖的人要在zk的特定目錄下創(chuàng)建一個臨時節(jié)點,并標明是讀鎖還是寫鎖。那么,這個目錄下所有的節(jié)點都是想要獲取鎖的人。接下來就監(jiān)聽在這個目錄下,有通知了,就表示有新的人要獲取鎖了。因為有很多人想獲取鎖,那么就要有個先后順序,順序由節(jié)點的順序決定。 接著,就是節(jié)點的順序問題了,如果都是讀鎖,那么順序不影響;如果都是寫鎖,就得嚴格按照節(jié)點的順序來決定獲取寫鎖的順序;如果兩種鎖混雜,節(jié)點的順序是會影響到獲取鎖的順序的。對于這樣的場景,實現邏輯是這樣的: (1)如果當前需要獲取讀鎖,則判斷該節(jié)點前面是否有比自己序號小的寫節(jié)點,如果有,那么肯定得先等那個寫節(jié)點獲取寫鎖釋放之后才輪到自己;如果沒有,那么表示在自己前面的都是讀鎖,大家可以不用等待,可以一起獲取讀鎖了。 (2)如果當前需要獲取寫鎖,就需要看自己是不是序號最小的節(jié)點了,如果不是,那么意味著前面的寫節(jié)點和讀節(jié)點,無論是哪個,都不能讓自己獲取到寫鎖的。 最后,因為創(chuàng)建的節(jié)點都是臨時節(jié)點,所以只要斷開會話,就會自動刪除,也就實現了鎖的釋放。


7、隊列管理

分布式系統(tǒng)中,非常重要的一個組件就是消息隊列,可以實現應用解耦,異步消息,流量消減。首先傳統(tǒng)的用戶請求都是請求者直接發(fā)給服務器,服務器處理完成之后在將結果返回給請求者,這樣會導致一個問題就是請求者在發(fā)出請求后會阻塞住,在收到服務器回復之前什么都干不了,而如果引入了消息隊列,那么這個處理的流程就會變成請求者先把請求發(fā)給消息隊列,然后服務器在從消息隊列獲得需要處理的消息,處理完成之后在將結果返回給請求者,這種方式下,請求者只要把請求發(fā)給消息隊列就可以干其他事情了,這樣就實現了請求的異步處理,也解除了請求者和服務器之間的耦合。 而在典型的大流量場景中,大量請求涌入到服務器時,會造成服務的癱瘓,所以需要有有個限流措施,但是又不至于丟失請求。所以需要一個組件將請求暫存,然后以一定的速度轉發(fā)給服務器進行處理,這個組件就是消息隊列。這種做法稱為流量消減。 還有典型的搶購場景中,大量搶購請求會涌入到服務器中,為了防止服務器崩潰??梢允褂孟㈥犃校㈥犃械拇笮≡O置為搶購數量的大小,超過則返回失敗,也就搶不到東西了。成功的就會暫存在隊列中,給服務器慢慢處理。 zk實現隊列很簡單,就是在特定目錄下創(chuàng)建節(jié)點,存儲請求。然后服務器依次從該目錄下讀取節(jié)點中的請求,處理并返回結果。處理完成后刪除節(jié)點。



向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI