溫馨提示×

溫馨提示×

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

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

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

發(fā)布時間:2021-10-25 14:40:07 來源:億速云 閱讀:127 作者:iii 欄目:編程語言

這篇文章主要講解了“分布式協(xié)調服務組件Zookeeper的必備知識點有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“分布式協(xié)調服務組件Zookeeper的必備知識點有哪些”吧!

分布式協(xié)調服務組件Zookeeper必備知識點

Zookeeper介紹


Zookeeper是一個開源的分布式協(xié)調服務組件。是分布式集群的監(jiān)控者,能對集群中節(jié)點的狀態(tài)變更進行及時的反饋。

Zookeeper對分布式一致性的保證:

  • 順序一致性:保證服務端的執(zhí)行順序是按照客戶端操作的發(fā)送順序來執(zhí)行的

  • 原子性:客戶端操作結果要么成功、要么失敗。

  • 單一視圖:無論客戶端連接到那個服務端,看到的視圖是一致的。

  • 可靠性:客戶端操作請求一定執(zhí)行成功,則執(zhí)行結果會一直持久到下一次操作

  • 最終一致性:保證一定時間內客戶端看到的視圖是最新的數(shù)據(允許一定時間內看到的數(shù)據不是最新的)

Zookeeper默認保證客戶端拿到的視圖是連接到的服務器此時的順序一致性視圖,通過客戶端調用SyncCommand保證是客戶端看到的視圖是此時集群中所有節(jié)點的最新強一致性視圖。

注意:最終一致性存在在一段時間內客戶端看到的視圖不一定是最新數(shù)據

Zookeeper常用API


ZooKeeper -server host:port -client-configuration properties-file cmd args
	addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
	addauth scheme auth
	close 
	config [-c] [-w] [-s]
	connect host:port
	create [-s] [-e] [-c] [-t ttl] path [data] [acl]
	delete [-v version] path
	deleteall path [-b batch size]
	delquota [-n|-b] path
	get [-s] [-w] path
	getAcl [-s] path
	getAllChildrenNumber path
	getEphemerals path
	history 
	listquota path
	ls [-s] [-w] [-R] path
	printwatches on|off
	quit 
	reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
	redo cmdno
	removewatches path [-c|-d|-a] [-l]
	set [-s] [-v version] path data
	setAcl [-s] [-v version] [-R] path acl
	setquota -n|-b val path
	stat [-w] path
	sync path
	version 
	whoami

Zookeeper數(shù)據模型


Zookeeper數(shù)據是存儲在內存中的具有層次結構的命名空間,類似于多級別的文件目錄結構一樣,不同的是每個命名空間可以掛載數(shù)據。命名空間不應該使用以下字符:\u0000、\u0001-\u001F、\u007F、\ud800-uF8FF、\uFFF0-uFFFF、保留關鍵字:zookeeper。命名空間都是絕對路徑,不存在相對路徑,以斜杠路徑分隔符劃分層級。

/meta1                         /meta2
  |-- /meta1/node1    			 |-- /meta2/node1 
  |-- /meta1/node2     			 |--|--/meta2/node2/child 
  |--|-- /meta1/node3/child      |-- /meta2/node3  
  |-- /meta1/node4    			 |-- /meta2/node4

Zookeeper是Java語言開發(fā)的,節(jié)點稱為Znode,樹形存儲結構對象為:DataTree,節(jié)點存儲對象為:ConcurrentHashMap<String, DataNode> nodes。

Zookeeper節(jié)點本身存儲無大小限制,但是數(shù)據序列化傳輸時有限制,默認上限1M,可通過系統(tǒng)屬性:"jute.maxbuffer"配置,詳細可見類:BinaryInputArchive。但是Zookeeper在集群中節(jié)點數(shù)據傳輸較多,不建議存儲過大的數(shù)據,一旦修改該上限,集群中所有節(jié)點都要修改。

Zookeeper數(shù)據節(jié)點類型


Zookeeper支持四種類型的節(jié)點,節(jié)點只能逐個創(chuàng)建:v3.5.3+支持對持久節(jié)點設置TTL

  • 臨時節(jié)點(EPHEMERAL):節(jié)點生命周期綁定客戶端會話,在客戶端結束會話時會自動刪除,節(jié)點下不能創(chuàng)建新的節(jié)點

  • 臨時有序節(jié)點:(EPHEMERAL_SEQUENTIAL):具有臨時節(jié)點特點,節(jié)點創(chuàng)建后節(jié)點名自動追加序號,多次創(chuàng)建序號自增,10位數(shù)字

  • 持久節(jié)點(PERSISENT):持久落盤保存,重啟不丟失,需要手動調用delete命令刪除

  • 持久有序節(jié)點(PERSISTENT_SEQUENTIAL):具有持久節(jié)點特點,節(jié)點創(chuàng)建后節(jié)點名會自動追加序號,多次創(chuàng)建序號自增,10位數(shù)字

  • 容器節(jié)點(CONTAINER):當其子節(jié)點被完全刪除時,該節(jié)點會自動刪除

  • 限時節(jié)點(TTL):對持久節(jié)點增加限時時長,默認禁用該功能,啟用屬性為:zookeeper.extendedTypesEnabled

Zookeeper集群節(jié)點數(shù)量


Zookeeper在分布式協(xié)調中遵循ZAB協(xié)議,具有過半有效特點,要求集群節(jié)點數(shù)量符合:2N+1。也就是可以單機部署,集群部署最少3個節(jié)點,最多宕機1臺,否則集群不可用(永遠不會過半,也不會轉為單機運行,會報錯),這里也說明Zookeeper保證的是分布式中CAP定理中的CP,一致性和分區(qū)容錯性。注意:Zookeeper集群中最少時2臺機器就可以運行了,但是宕機任意一臺集群就不可用。

Zookeeper集群節(jié)點角色與狀態(tài)


在Zookeeper啟動同時會啟動一個線程輪詢服務器狀態(tài),每臺集群節(jié)點服務只會存在以下狀態(tài):

  • LOOKING:表示當前集群中不存在Leader節(jié)點,集群中所有可參與選舉的節(jié)點正在進行Leader節(jié)點選舉

  • LEADING:表示該節(jié)點是集群中的領導者leader

    • leader角色具有對外提供讀寫視圖能力,集群中只有Leader節(jié)點能執(zhí)行事務(增、刪、改)操作,其他節(jié)點都需要轉發(fā)到Leader來執(zhí)行

  • FOLLOWING:表示該節(jié)點是集群中的跟隨者follower,說明當前集群中存在某個其他節(jié)點已經是Leader節(jié)點。

    • follower角色具有同步視圖數(shù)據、轉發(fā)事務請求到Leader以及對外提供讀視圖能力,在Zookeeper中配置為participant:參與者

  • OBSERVING:表示該節(jié)點是集群中的觀察者Observer

    • Observer角色主要擴展集群的非事務處理能力,對外提供讀視圖能力、轉發(fā)事務請求到Leader,不具有選舉能力。

    • observer與Follower統(tǒng)稱為learner

Zookeeper的二階段提交2PC


二階段提交是為保證分布式系統(tǒng)中數(shù)據的一致性而將事務操作行為分為兩個階段來完成。

第一階段:leader服務節(jié)點將該事務請求是否能夠執(zhí)行通過提議方式詢問集群中的所有Follower節(jié)點,各個Follower節(jié)點對該提議進行確認ACK。

第二階段:Leader對收到的ACK進行過半判斷,判定成功則進行事務提交,異步通知各Follower節(jié)點也進行事務提交。如果判定失敗則進行事務回滾。

事務一般都是通過日志文件的形式來實現(xiàn)的,zookeeper也不例外。第一階段針對事務請求會先進行日志記錄,然后發(fā)出詢問。在第二階段收到各Follower節(jié)點確認后,根據之前的日志,更新數(shù)據庫來完成事務。

Zookeeper的ZAB(ZooKeeper Atomic Broadcast)協(xié)議:zookeeper原子廣播協(xié)議


主要指2兩種運行狀態(tài),在Leader失聯(lián)時進入崩潰恢復狀態(tài),進行Leader選舉,當選舉完成后進入原子廣播協(xié)議,Leader節(jié)點將事務請求廣播到Follower節(jié)點

Zookeeper的Leader選舉


Zookeeper集群中是必須要一臺Leader角色的節(jié)點的,在不存在Leader節(jié)點時就需要集群內部自行選舉,這種情況分為兩種:1:集群首次啟動時,2:集群中Leader節(jié)點失聯(lián)時,二者的選舉流程一致,只是前者時啟動時發(fā)現(xiàn)Leader不存在,后者是運行時發(fā)現(xiàn)Leader失聯(lián)。

Zookeeper節(jié)點啟動時默認的狀態(tài)為:LOOKING,即集群中不存在Leader節(jié)點,需要進行Leader選舉。對于節(jié)點狀態(tài)的監(jiān)控是一個死循環(huán),隨服務啟動而開始,隨服務停止而結束,因此首次啟動會立馬根據選舉算法開始Leader選舉,v3.5+選舉算法只有一個: FastLeaderElection

在Zookeeper的選票中存在四個很重要的數(shù)據:myid(集群服務ID)、zxid(事務ID)、peerEpoch(leader輪期)、electionEpoch(選舉輪次)。

  • myid表示集群節(jié)點的服務唯一ID,這是配置文件中配置的ID,是身份識別碼。

  • zxid表示集群節(jié)點中記錄的事務日志ID,是一個64位Long類型數(shù)字,其中高32位為epoch,低32位為自增計數(shù)器counter。

    • epoch則表示當前集群中Leader所處的輪期,每次Leader變更都會自增1,是Zxid的高32位。

  • electionEpoch表示自節(jié)點啟動時集群中進行過Leader選舉的輪次,每次Leader選舉內部多個輪次

zxid結構如下

public static long makeZxid(long epoch, long counter) {
  return (epoch << 32L) | (counter & 0xffffffffL);
}

zxid整體是自增的,Zookeeper通過自增來保證數(shù)據的順序性。根據Zookeeper保證的順序一致性:zxid越大則該事務執(zhí)行的越晚,保存的數(shù)據越完整。

Leader選舉前后要保證的就是數(shù)據的盡可能一致性,因此Leader選舉的實質就是找出存活的Follower節(jié)點中數(shù)據保存最完善的那一臺作為Leader。

尋找方式就是比較zxid大小。如果zxid都一致,則說明存活的Follower節(jié)點數(shù)據保存完整性是一樣的,隨便選一臺都行,Zookeeper默認選中myid最大的那一臺。

尋找算法則是FastLeaderElection的實現(xiàn)過程

在Leader選舉流程中,存在一個阻塞隊列,用來接收其他集群節(jié)點中發(fā)送的選票,而當前節(jié)點也會持有一個選票。選票內容主要包括:myid(集群節(jié)點身份識別唯一ID)、zxid(集群節(jié)點最大事務日志ID)、peerEpoch(集群節(jié)點事務所處輪期)、electionEpoch(集群已進行Leader選舉的次數(shù))。

在選舉流程開始時首先將投向自己的選票(選票內容均指向自身節(jié)點信息)發(fā)送出去,由于機器中節(jié)點在啟動時都會發(fā)送一個選票,因此阻塞隊列就會收到其他節(jié)點的選票。選票的發(fā)送屬于異步發(fā)送,方法為:sendNotifications,先把內容ToSend放入阻塞隊列,然后發(fā)送線程去逐個發(fā)送。

節(jié)點使用logicalclock(邏輯時鐘)來記錄當前集群進行Leader選舉的輪次electionEpoch。并在每次投票之后以輪次為基礎進行流水記錄,便于后續(xù)分析,節(jié)點只記錄最新輪次的投票流水。

當其他節(jié)點的electionEpoch大于當前節(jié)點的electionEpoch時,說明,當前節(jié)點錯過了某輪投票,需要更新logicalclock,并在選票PK之后更新自身持有的投票信息,為數(shù)據較為完整的節(jié)點投上一票。(說明之前的投票所處輪次已過時,需要為最新輪次重新投一票)

// 選票PK方法
return ((newEpoch > curEpoch)|| ((newEpoch == curEpoch) && ((newZxid > curZxid)|| ((newZxid == curZxid)&& (newId > curId)))));

當其他節(jié)點的electionEpoch小于當前節(jié)點的electionEpoch時,說明,其他節(jié)點錯過了某輪投票,本身之前投票記錄是有效的,其他節(jié)點的投票所處輪次是過時,因此舍棄這個過時投票,不參與統(tǒng)計。(本身的票已經投出去了,不需要重復投票)

當其他節(jié)點的electionEpoch等于當前節(jié)點的electionEpoch時,說明,兩者節(jié)點都是正常投票,則進行選票PK,比較本節(jié)點的zxid、myid和選票節(jié)點的對應值大小。哪個節(jié)點的值大則說明哪個節(jié)點記錄的數(shù)據較為完整,此時需要更新選票信息,為數(shù)據較為完整的節(jié)點投上一票。(說明之前的投票的節(jié)點數(shù)據不是集群中記錄最完整的,需要重新投一票)

以輪次為基礎,為數(shù)據較為完整的節(jié)點投上一票后,阻塞隊列就又接收到了新一批選票,然后再次比較,依次循環(huán)下去

Leader選舉就是選出數(shù)據最完整的那臺節(jié)點,因此選舉流程不會一直循環(huán)PK下去,會在流水記錄符合過半確認時終止循環(huán)。而這個判斷條件是在為可能完整節(jié)點投票后,以服務ID為表示,記錄集群中為該服務節(jié)點投票信息,當集群中過半節(jié)點都對該節(jié)點投了票時就認定該節(jié)點有資格成為Leader節(jié)點,從而結束Leader選舉。

圖示如下

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

Zookeeper的數(shù)據同步


Zookeeper集群中選舉出Leader節(jié)點后,Leader節(jié)點會進行LEADING狀態(tài)。Follower節(jié)點則會進行FOLLOWING狀態(tài),開啟Leader確認、同步流程。而observer節(jié)點則進入OBSERVING狀態(tài),同樣準備進入同步流程。

Leader節(jié)點

預選Leader節(jié)點會先與Learner節(jié)點建立網絡連接,等待Follower、Observer節(jié)點接入。

cnxAcceptor = new LearnerCnxAcceptor();
// 這是一個連接線程
cnxAcceptor.start();

這個網絡連接十分重要,每個Leader會構建一個LearnerCnxAcceptorHandler的處理器,核心過程如下

BufferedInputStream is = new BufferedInputStream(socket.getInputStream());
LearnerHandler fh = new LearnerHandler(socket, is, Leader.this);
fh.start();

這個LearnerHandler處理所有Leader與learner的網絡IO交互

消息包
public class QuorumPacket implements Record {
  private int type;
  private long zxid;
  private byte[] data;
  private java.util.List<org.apache.zookeeper.data.Id> authinfo;
}
1.--> learner節(jié)點

Follower節(jié)點進入FOLLOWING狀態(tài)后,首先會去查找Leader地址,然后建立網絡連接

QuorumServer leaderServer = findLeader();
connectToLeader(leaderServer.addr, leaderServer.hostname);

建立連接之后便發(fā)出type=FOLLOWERINFO的消息包,xid=ZxidUtils.makeZxid(self.getAcceptedEpoch(), 0),data=LearnerInfo

主要功能就是將當前節(jié)點的epoch發(fā)送(所有連接節(jié)點都會發(fā)送INFO信息來給Leader提供集群中最大的epoch,以便確認Leader的最新任期:lastAcceptedEpoch + 1,Leader節(jié)點會阻塞等待Follower節(jié)點接入直至滿足過半確認時獲取最大的epoch)

long newEpochZxid = registerWithLeader(Leader.FOLLOWERINFO);

消息發(fā)出后等待Leader節(jié)點指示

2.--> Leader節(jié)點

Follower發(fā)出的FOLLOWERINFO消息包會在LearnerHandler被接收轉為:learnerInfoData,獲取Follower提供的zxid中的epoch

 long lastAcceptedEpoch = ZxidUtils.getEpochFromZxid(qp.getZxid());

然后參與到新任Leader的epoch選舉中

long newEpoch = learnerMaster.getEpochToPropose(this.getSid(), lastAcceptedEpoch);

Leader接收到過半Follower提供的epoch后,發(fā)送最終epoch確認消息包

QuorumPacket newEpochPacket = new QuorumPacket(Leader.LEADERINFO, newLeaderZxid, ver, null);

等待Follower確認最終的epoch

learnerMaster.waitForEpochAck(this.getSid(), ss);
3.--> learner節(jié)點

Follower之前阻塞在registerWithLeader中的INFO信息發(fā)送后,此時接收到Leader指示獲取Leader的epoch和zxid,發(fā)出確認接收消息

QuorumPacket ackNewEpoch = new QuorumPacket(Leader.ACKEPOCH, lastLoggedZxid, epochBytes, null);

在接收到Leader給的zxid后,將自身狀態(tài)設為同步狀態(tài),開啟數(shù)據同步流程,等待Leader的同步數(shù)據。

self.setZabState(QuorumPeer.ZabState.SYNCHRONIZATION);
syncWithLeader(newEpochZxid);
4.-->Leader節(jié)點

Leader接收到足夠的Follower的epoch確認消息后,將自身狀態(tài)設為數(shù)據同步狀態(tài),與各個Learner開啟數(shù)據同步,阻塞等待Learner數(shù)據同步完成然后執(zhí)行自身的Leading

waitForNewLeaderAck(self.getId(), zk.getZxid());

數(shù)據同步發(fā)生在各個Leader建立的網絡連接中:LearnerHandler,在確認到Learner接收了最新epoch消息后,立馬開啟數(shù)據同步流程

boolean needSnap = syncFollower(peerLastZxid, learnerMaster);

同步過程使用重入讀寫鎖:ReentrantReadWriteLock。并且獲取此Leader節(jié)點的lastProcessedZxid、minCommittedLog、maxCommittedLog

同步類型:DIFF:差異同步、TRUNC:回滾同步、SNAP: 全量同步,主要是TRUNC+DIFF,也就是learner上事務日志比leader上多的zxid進行回滾,少的從leader接收進行重做。

只有系統(tǒng)變量:zookeeper.forceSnapshotSync 配置了強制全量同步時,會使用快照文件開啟全量同步。

到底是learner的事務日志多還是leader節(jié)點的事務日志多,是通過兩個節(jié)點的zxid比較的。事務日志是會落盤形成快照的,節(jié)點會緩存一定條數(shù)的事務日志,那部分具有minCommittedLog、maxCommittedLog的范圍屬性。在此范圍的數(shù)據可以直接發(fā)送,否則需要從磁盤讀取快照文件再次發(fā)送。

系統(tǒng)變量:zookeeper.snapshotSizeFactor 配置每次從磁盤讀取的快照數(shù)據所占快照總數(shù)的比例,默認0.33即三分之一

系統(tǒng)變量:zookeeper.commitLogCount 配置節(jié)點緩存的事務日志數(shù)量,默認500條

5.--> learner節(jié)點

Follower節(jié)點阻塞在syncWithLeader中等待Leader同步的數(shù)據,Leader同步數(shù)據主要就三種,DIFF、TRUNC、SNAP。其中DIFF是逐條的執(zhí)行提議,F(xiàn)ollower節(jié)點接收后會執(zhí)行,TRUNC接收到Follower則直接截斷日志文件到指定位置即可,對于SNAP則清空dataTree根據傳輸?shù)娜罩疚募葱蛄屑纯?。處理完畢則發(fā)送確認消息,正式對外提供服務。Leader節(jié)點接收到Follower的同步結束消息后,結束waitForNewLeaderAck,也會正式對外提供服務。

同步數(shù)據主流程如圖所示

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

數(shù)據同步細節(jié)如圖所示

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

Zookeeper的Watch機制


Zookeeper支持客戶端對數(shù)據節(jié)點Znode注冊Watch監(jiān)聽,當節(jié)點發(fā)生變化會及時反饋給該客戶端。Watch機制是Zookeeper分布式鎖、對外Leader選舉功能的基礎。

watch類型

v3.6.0之前:watch是一次性注冊,一旦反饋后會刪除,如果需要重復監(jiān)聽,則需要重復注冊

v3.6.0+ :支持配置監(jiān)聽模式:STANDARD(標準類型)、PERSISTENT(持久類型)、PERSISTENT_RECURSIVE(持久遞歸類型)。標準類型就是之前版本的一次性注冊類型;持久類型則是自動重復注冊類型;持久遞歸類型則是持久類型的加強版本,不僅重復監(jiān)聽指定節(jié)點,還重復監(jiān)聽節(jié)點的子節(jié)點。后兩種模式需要主動移除Watch才能取消監(jiān)聽。

API

支持Watch的API:exist、getData、getChildren、addWatch

移除Watch的API:removeWatches

觸發(fā)Watch的API:setData、delete、create

保證
  • 只有注冊了Watch監(jiān)聽的客戶端才會收到反饋通知

  • 客戶端收到的反饋通知順序與服務端節(jié)點處理順序一致

注意
  • Watch依賴網絡連接的一次性通知,客戶端重連期間可能會導致Wacth丟失

  • 標準Watch是一次性,多次觸發(fā)的Watch如果客戶端沒有來得及重置,會導致后續(xù)Watch通知丟失

  • 標準Watch是一次性,持久Wach是服務端自動注冊的,實質還是一次性通知

  • 持久Watch如果不主動移除會一直通知下去

步驟
  1. 客戶端對指定節(jié)點注冊Watch

  2. 服務保存Watch,一旦觸發(fā)事件則發(fā)送消息通知

  3. 客戶端回調watch事件,進一步處理

原理

Watch監(jiān)聽注冊對象在Zookeeper中為WatchRegistration,不同API對應的注冊對象不同

// getData、getConfig   --->  DataWatchRegistration
public class GetDataRequest implements Record {
  private String path;
  private boolean watch;
}

// exists --->  ExistsWatchRegistration
public class ExistsRequest implements Record {
  private String path;
  private boolean watch;
}

// getChildren --> ChildWatchRegistration 
public class GetChildrenRequest implements Record {
  private String path;
  private boolean watch;
}

// @since 3.6.0  addWatch --> AddWatchRegistration
public class AddWatchRequest implements Record {
  private String path;
  private int mode;
}

這個請求又一個很明顯特點:watch是一個布爾類型,也就是說只標識是否watch

watch注冊


1.--> 客戶端:在發(fā)起API請求時構建queuePacket對象。該對象主要包含RequestHeader、ReplyHeader、Record(Request)、Record(Response)、WatchRegistration等。其中RequestHeader標記本次請求的操作類型 type 和事務zxid。服務端根據操作類型會有不同的解析流程。在queuePacket的構造方法中會把queuePacket放入到一個阻塞隊列中outgoingQueue,該隊列會有專用的線程sendThread#clientCnxnSocket#doTransport從隊列中讀取元素并處理。如果是事務請求則把zxid++,然后序列化RequestHeader和Request,只把這兩者發(fā)送出去。queuePacket會放到pendingQueue中等待服務器返回,也就是說WatchRegistration并沒有發(fā)送出去,只是發(fā)送了操作標識、zxi、path、watch標志。

2.--> 服務端:在Zookeeper啟動時會通過startServerCnxnFactory開啟服務端連接,此時會開啟AcceptThread來處理客戶端的連接,客戶端建立連接時會在這里處理,在接入時會構建SelectorThread來通過handleIO處理客戶端的IO請求,然后將以此IO交互抽象為IOWorkRequest交給線程池去異步處理doWork-->doIO,然后開始解析網絡消息包readPayload,然后解析消息包processPacket,解析之后放到阻塞隊列submittedRequests中,隊列請求在RequestThrottler中處理,然后submitRequestNow交給ZkServer的處理鏈去鏈式處理。處理鏈初始化時指定了FinalRequestProcessor會處理與數(shù)據庫的交互。根據操作標識type不同有不同的解析流程并反序列化數(shù)據構建對應的Request。如果Request中存儲watch標識則在DataTree中通過IWatchManager添加記錄,記錄包含監(jiān)聽的路徑Path和客戶端的連接ServerCnxn等,這步就是服務端注冊,這里IWatchManager區(qū)分為當前節(jié)點和子節(jié)點2種。

private IWatchManager dataWatches;

private IWatchManager childWatches;

將Request處理完畢就寫入Response中,構建ReplyHeader、操作標識、響應狀態(tài)stat等返回了

3.--> 客戶端:在SendThread#readResponse中接收服務端的響應,此時阻塞隊列pendingQueue中取出之前outgoingQueue中保存的queuePacket對象,處理好響應內容就finishPacket,此時客戶端就完成Watch注冊和對應API功能的響應。finishPacket接收的是queuePacket對象,會處理其中的WatchRegistration,調用其register方法。register首先會拿到客戶端的ZKWatchManager中對應類型的存儲列表。其中ZKWatchManager存儲以下列表

private final Map<String, Set<Watcher>> dataWatches = new HashMap<>();
private final Map<String, Set<Watcher>> existWatches = new HashMap<>();
private final Map<String, Set<Watcher>> childWatches = new HashMap<>();
private final Map<String, Set<Watcher>> persistentWatches = new HashMap<>();
private final Map<String, Set<Watcher>> persistentRecursiveWatches = new HashMap<>();

不同Map存儲不同類型的Watcher,register方法就是將WatchRegistration的實例存儲到HashMap中。這就是客戶端注冊。

圖示如下

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

Watch觸發(fā)


1.--> 客戶端:當節(jié)點發(fā)送NodeCreated,NodeDeleted、NodeDataChanged、NodeChildrenChanged事件時,會觸發(fā)Watch反饋,對應API為:create、delete、setData。

2.--> 服務端:在以上API操作DataTree數(shù)據時,會觸發(fā)IWatchManager#triggerWatch,不同API觸發(fā)的事件類型不同。triggerWatch會查詢相關Watch并調用其process放啊,當然這是服務端的watch,也就是在服務端注冊的與操作節(jié)點Path相關的ServerCnxn。此時ServerCnxn會構建一個notification類型客戶端響應并發(fā)送給客戶端。如果WatchMode是默認類型則觸發(fā)一次就移除了Watch標識,否則會持續(xù)觸發(fā)。

public static final WatcherMode DEFAULT_WATCHER_MODE = WatcherMode.STANDARD;

3.--> 客戶端:同樣在SendThread#readResponse中接收服務端的響應,解析是發(fā)現(xiàn)是notification類型響應,則構建一個WatcherEvent,通過eventThread.queueEvent(we)構建事件和對應Watch列表的WatcherSetEventPair對象,然后放入阻塞隊列waitingEvents。構建WatcherSetEventPair時會查找所有在客戶端ZKWatchManager中注冊的對指定事件感興趣的客戶端Watch。EventThread則不斷從waitingEvents取出事件,如果是WatcherSetEventPair則遍歷調用Watch的process方法,該方法就是客戶端需要重新的Watch監(jiān)聽處理方法。這樣就完成了整個Watch觸發(fā)機制

圖示如下

分布式協(xié)調服務組件Zookeeper的必備知識點有哪些

Zookeeper的Chroot特性


在V3.2.0+ 添加了 Chroot 特性,該特性允許每個客戶端為自己設置一個命名空間。這樣客戶端的所有操作都會在改命名空間下面,生成數(shù)據隔離。

Zookeeper的權限控制


Zookeeper支持對每個節(jié)點配置ACL權限,其中添加認證用戶命令為:addauth scheme auth ,auth格式為:<username>:<passwprd>

ACL權限方案

方案

描述

設置命令

world

只有一個用戶:anyone,代表所有人(默認)

setAcl path world:anyobe:acl

ip

使用IP地址認證

setAcl path ip:<ip>:acl

auth

使用已添加認證的用戶認證

setAcl path auth:<username>:acl

digest

使用“用戶名:密碼”方式認證

setAcl path digest:<username>:<passwprd>:acl

ACL權限標識  

權限

ACL簡寫

描述

CREATE

c

可以創(chuàng)建子節(jié)點(只能逐級創(chuàng)建,不能跨級別創(chuàng)建節(jié)點)

DELETE

d

可以刪除子節(jié)點(僅下一級節(jié)點)

READ

r

可以讀取節(jié)點數(shù)據及顯示子節(jié)點列表

WRITE

w

可以設置節(jié)點數(shù)據

ADMIN

a

可以設置節(jié)點訪問控制列表權限

Zookeeper集群宕機與動態(tài)擴容

集群數(shù)量符合2N+1原則,當集群宕機數(shù)量少于1/2時,仍然能對外服務

v3.5.0+ 支持集群動態(tài)配置,在主配置文件開啟屬性reconfigEnabled=true,配置屬性為:dynamicConfigFile= basePath/fileName ,動態(tài)配置文件名格式為:configFilename.dynamic[.version]。 內容只支持server、group 、 weight屬性,其中server配置格式為

server.<positive id> = <address1>:<port1>:<port2>[:role];[<client port address>:]<client port>

角色role可選值為:participant(參與者,運行中為follower,默認值)、observer(觀察者)。修改后需要調用客戶端命令reconfig

Zookeeper集群監(jiān)控

v3.6.0+ 支持度量指標監(jiān)控,可配合Prometheus.io通過Jetty服務器對外輸出。訪問地址為:http://hostname:httPort/metrics。此時可以使用grafana進行可視化監(jiān)控。

感謝各位的閱讀,以上就是“分布式協(xié)調服務組件Zookeeper的必備知識點有哪些”的內容了,經過本文的學習后,相信大家對分布式協(xié)調服務組件Zookeeper的必備知識點有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

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

AI