zk技術(shù)內(nèi)幕

一场刑、系統(tǒng)模型

1鳄乏、數(shù)據(jù)模型
  • zk結(jié)構(gòu)視圖與unix的文件系統(tǒng)有點(diǎn)類似,但是沒有目錄和文件的相關(guān)概念区丑。而是使用特有的數(shù)據(jù)節(jié)點(diǎn)的概念拧粪,稱為zNode節(jié)點(diǎn),zNode節(jié)點(diǎn)是zk中數(shù)據(jù)最小的單元沧侥,每個zNode都可以保存數(shù)據(jù)可霎,通是還可以掛載子節(jié)點(diǎn),因此構(gòu)成了一個層次化的空間命名正什,稱之為數(shù)啥纸。
  • zk中的zNode的節(jié)點(diǎn)路徑標(biāo)識方式和unix文件系統(tǒng)路徑類似,都是一些列的斜杠(/)進(jìn)行分割的路徑標(biāo)識婴氮,可以在節(jié)點(diǎn)中寫入數(shù)據(jù)斯棒,也可以再節(jié)點(diǎn)下面創(chuàng)建子節(jié)點(diǎn)。


    zk數(shù)據(jù)模型
  • 事務(wù)ID:事務(wù)是對物理和抽象的應(yīng)用狀態(tài)上的操作集合主经。在zk中事務(wù)是指能夠改變zk服務(wù)器狀態(tài)的操作荣暮,我們稱之為事務(wù)操作或者更新操作,一般包括數(shù)據(jù)節(jié)點(diǎn)創(chuàng)建于刪除罩驻,數(shù)據(jù)節(jié)點(diǎn)內(nèi)容更新和客戶端會話創(chuàng)建與失效等操作穗酥。對于zk的一個事物請求,zk都會為其分配一個全局唯一的事務(wù)id惠遏,用zxid來表示砾跃,通常是一個64位的數(shù)字。
2节吮、節(jié)點(diǎn)特征

(1) 節(jié)點(diǎn)類型:在zk中每一個節(jié)點(diǎn)都是有什么周期的抽高,具體生命周期的長度取決于數(shù)據(jù)節(jié)點(diǎn)的節(jié)點(diǎn)類型。zk中節(jié)點(diǎn)類型分為持久節(jié)點(diǎn)(PERSISTENT)透绩、臨時(shí)節(jié)點(diǎn)(EPHEMERAL)和順序節(jié)點(diǎn)(SEQUENTIAL)三類翘骂,并通過組合可以組成下面四種類型:

1壁熄、持久節(jié)點(diǎn):所謂持久節(jié)點(diǎn)就是該數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建后,就會一直存在于zk服務(wù)器中碳竟,直到有刪除操作來主動清除這個節(jié)點(diǎn)草丧。
2、持久順序節(jié)點(diǎn):在zk中莹桅,每一個父節(jié)點(diǎn)都會為它的第一級子節(jié)點(diǎn)維護(hù)一份順序昌执,用于記錄下每個子節(jié)點(diǎn)創(chuàng)建的先后順序,基于這個順序特性统翩,在創(chuàng)建子節(jié)點(diǎn)的時(shí)候仙蚜,可以設(shè)置這個標(biāo)記,那么在創(chuàng)建子節(jié)點(diǎn)過程中厂汗,zk會自動為給定節(jié)點(diǎn)加上一個數(shù)字后綴委粉,作為一個新的、完整的節(jié)點(diǎn)名娶桦。(數(shù)字上限為整形最大值)
3贾节、臨時(shí)節(jié)點(diǎn):臨時(shí)節(jié)點(diǎn)的生命周和客戶端的會話綁定在一起,也就是說這個客戶端失效衷畦,那么這個節(jié)點(diǎn)就會被自動清理掉栗涂。同時(shí)規(guī)定,臨時(shí)節(jié)點(diǎn)不能創(chuàng)建子節(jié)點(diǎn)祈争,臨時(shí)節(jié)點(diǎn)只能作為葉節(jié)點(diǎn)存在泞边。
4撼玄、臨時(shí)順序節(jié)點(diǎn):就是在臨時(shí)節(jié)點(diǎn)的基礎(chǔ)之上,添加了順序的特性。

(2)狀態(tài)信息:zk數(shù)據(jù)節(jié)點(diǎn)除了存儲了數(shù)據(jù)內(nèi)容之外囤躁,還存儲了數(shù)據(jù)節(jié)點(diǎn)本身的一些狀態(tài)信息长豁∷甭茫可以通過get來查看一個數(shù)據(jù)節(jié)點(diǎn)的內(nèi)容生宛,如圖所示,第一行是數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容邢疙,第二行開始就是數(shù)據(jù)節(jié)點(diǎn)的狀態(tài)信息棍弄,其實(shí)就是數(shù)據(jù)節(jié)點(diǎn)的stat對象的格式化輸出

數(shù)據(jù)節(jié)點(diǎn)信息和內(nèi)容

  • Stat類包含了zk上的一個數(shù)據(jù)節(jié)點(diǎn)的所有狀態(tài)信息,包括事務(wù)id疟游、版本信息和子節(jié)點(diǎn)個數(shù)呼畸。
屬性 說明
czxid 表示數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建時(shí)候的事務(wù)id
mzid 節(jié)點(diǎn)最后一次被更新的事務(wù)id
ctime 節(jié)點(diǎn)被創(chuàng)建的時(shí)間
mtime 節(jié)點(diǎn)最后一次被更新的時(shí)間
version 數(shù)據(jù)節(jié)點(diǎn)的版本號
cversion 子節(jié)點(diǎn)的版本號
aversion 節(jié)點(diǎn)acl的版本號
ephemeralOwner 創(chuàng)建臨時(shí)節(jié)點(diǎn)的會話id
dataLength 數(shù)據(jù)內(nèi)容的長度
pzxid 該節(jié)點(diǎn)的子節(jié)點(diǎn)列表最后被修改的事物id
numChildren 當(dāng)前子節(jié)點(diǎn)的個數(shù)
3、版本

(1)悲觀鎖和樂觀鎖:

悲觀鎖:稱為悲觀并發(fā)控制(PCC)颁虐,具有強(qiáng)烈的獨(dú)占性和排他性役耕,能夠有效的額避免不同事務(wù)對同一個數(shù)據(jù)并發(fā)更新而造成的數(shù)據(jù)一致性問題。一般認(rèn)為聪廉,在實(shí)際生產(chǎn)中瞬痘,悲觀鎖策略適合解決那些對于數(shù)據(jù)更新競爭十分激烈的場景。
樂觀鎖:稱樂觀并發(fā)控制(OCC)板熊,悲觀鎖假定事務(wù)之間一定會出現(xiàn)互相干擾框全,而樂觀鎖則認(rèn)為多個事務(wù)之間在處理過程中不會彼此影響(不總是會影響),因此在事務(wù)處理的絕大部分時(shí)間里不需要進(jìn)行加鎖處理干签。但是有并發(fā)一定存在者更新數(shù)據(jù)的沖突津辩。(樂觀鎖機(jī)制就是更新請求提交之前,每一個事務(wù)都會首先檢查當(dāng)前事務(wù)讀取數(shù)據(jù)后容劳,是否還有其他事務(wù)對該數(shù)據(jù)進(jìn)行了修改喘沿。如果其他事務(wù)有更新的話,那么正在提交的事務(wù)就需要回滾竭贩。)樂觀鎖通常用在數(shù)據(jù)并發(fā)競爭不大蚜印,事務(wù)沖突較少的場景中。

(2)樂觀鎖詳解
一般樂觀鎖對事務(wù)的控制分為三階段:數(shù)據(jù)讀取留量、寫入效驗(yàn)窄赋、數(shù)據(jù)寫入,其中寫入效驗(yàn)是整個樂觀鎖關(guān)鍵所在楼熄。再寫入效驗(yàn)階段忆绰,事務(wù)會檢查數(shù)據(jù)在讀取節(jié)點(diǎn)后是否還有其他事務(wù)對數(shù)據(jù)進(jìn)行過更新,以確保數(shù)據(jù)更新的一致性可岂。(實(shí)現(xiàn)樂觀鎖可以基于CAS原理和版本控制)

CAS原理:對于值V错敢,每一次更新前都會對比其值是否是預(yù)期值A(chǔ),只有符合預(yù)期值缕粹,才會將V原子化的更新為新值B稚茅。

(3)zk中版本控制實(shí)現(xiàn)樂觀鎖

  • 在zk中,每一個節(jié)點(diǎn)都有三種不同的版本信息(version致开、cversion峰锁、aversion),對數(shù)據(jù)節(jié)點(diǎn)的任何操作都會引起版本號的變化双戳。以version為例說明虹蒋。當(dāng)一個數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建后,version為0,(表示數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建后飒货,被更新過0次)魄衅,如果對該節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容進(jìn)行了更新操作,那么version的值就會變?yōu)?塘辅,這里的變更強(qiáng)調(diào)的是變更次數(shù)晃虫,即時(shí)變更內(nèi)容不變,version的值還是會發(fā)生變化的扣墩。
  • zk中version參數(shù)正是CAS原理演化過來的哲银,具體實(shí)現(xiàn)過程為:

加入一個客戶端試圖進(jìn)行更新操作扛吞,它會攜帶上次獲取到的version值進(jìn)行更新,如果在這個時(shí)間內(nèi)荆责,zk服務(wù)器上該節(jié)點(diǎn)的數(shù)據(jù)恰好已經(jīng)被其他客戶端更新了滥比,那么其數(shù)據(jù)版本一定也發(fā)生了變化,因此肯定與客戶端攜帶的version無法匹配做院,也就無法更新成功盲泛,這樣可以有效的避免了一些分布式更新問題。而version這個參數(shù)就充當(dāng)了CAS中的“預(yù)期值”

  • 原理
//獲取值V
 version = setDataRequest.getVersion();
//獲取zk版本號預(yù)期值A(chǔ)
            currentVersion = nodeRecord.stat.getVersion();
//如果A是-1键耕,說明沒有并不要求使用樂觀鎖寺滚;如果不為-1,那么進(jìn)行A和V對比
//不匹配就拋出異常
            if (version != -1 && version != currentVersion) {
                throw new BadVersionException(path);
            }
            version = currentVersion + 1;
4屈雄、zk數(shù)據(jù)節(jié)點(diǎn)小結(jié)
  • 如下圖所示村视,zk的數(shù)據(jù)節(jié)點(diǎn)有以下特征:

1、每個子目錄項(xiàng)如NameService都被稱作znode,這個znode是被它所在的路徑唯一標(biāo)識,如Server1這個znode的標(biāo)識為/NameService/Server1
2棚亩、znode可以有子節(jié)點(diǎn)目錄,并且每個znode可以存儲數(shù)據(jù),注意EPHEMERAL類型的目錄節(jié)點(diǎn)不能有子節(jié)點(diǎn)目錄
3蓖议、znode是有版本的,每個znode中存儲的數(shù)據(jù)可以有多個版本,也就是一個訪問路徑中可以存儲多份數(shù)據(jù)
4、znode可以是臨時(shí)節(jié)點(diǎn),一旦創(chuàng)建這個znode的客戶端與服務(wù)器失去聯(lián)系,這個znode也將自動刪除,ZooKeeper的客戶端和服務(wù)器通信采用長連接方式,每個客戶端和服務(wù)器通過心跳來保持連接,這個連接狀態(tài)成為session,如果znode是臨時(shí)節(jié)點(diǎn),這個session失效,znode也就被刪除.
5讥蟆、znode可以被監(jiān)控,包括這個目錄節(jié)點(diǎn)中存儲的數(shù)據(jù)被修改,子節(jié)點(diǎn)目錄的變化等,一旦變化可以通知設(shè)置監(jiān)控的客戶端,這個是ZooKeeper的核心特性.

zk數(shù)據(jù)結(jié)構(gòu)模型

二勒虾、Watch機(jī)制

  • zk中引入了watcher機(jī)制來實(shí)現(xiàn)分布式的發(fā)布、訂閱功能瘸彤。zk允許客戶端向服務(wù)器注冊一個watcher監(jiān)聽修然,當(dāng)服務(wù)器的一些指定事件觸發(fā)了這個watcher,那么就會向指定客戶端發(fā)送一個事件通知來實(shí)現(xiàn)分布式的通知功能质况。
  • 原理:zk中watcher機(jī)制主要包括客戶端線程愕宋、客戶端watchManager和zk服務(wù)器三個部位。具體工作流程中结榄,客戶端向zk服務(wù)器注冊watcher的同時(shí)中贝,會將watcher對象存儲在客戶端的watchManager中;當(dāng)zk服務(wù)器觸發(fā)watcher事件后臼朗,會向客戶端發(fā)送通知邻寿,客戶端線程從watchermanager中取出對應(yīng)的watcher對象來執(zhí)行回調(diào)邏輯。

(1)watcher接口

public interface Watcher {
//事件的回調(diào)方法视哑,當(dāng)zk向客戶端發(fā)送一個watcher事件通知時(shí)候绣否,客戶端就會
//對相應(yīng)的process方法進(jìn)行回調(diào),從而實(shí)現(xiàn)對事件的處理
    void process(WatchedEvent var1);
//事件通知類型
    public interface Event {
        public static enum EventType {
            None(-1),
            NodeCreated(1),
            NodeDeleted(2),
            NodeDataChanged(3),
            NodeChildrenChanged(4);
....
        }
//事件通知狀態(tài)
        public static enum KeeperState {
      ·    //客戶端與服務(wù)器斷開連接(此時(shí)處于斷開連接狀態(tài))
            Disconnected(0),
 //此時(shí)處于連接狀態(tài)(成功連接時(shí)候挡毅,觸發(fā)條件創(chuàng)建蒜撮、刪除、節(jié)點(diǎn)數(shù)據(jù)改變跪呈、子節(jié)點(diǎn)列表發(fā)生變化)
            SyncConnected(3),
            AuthFailed(4),
            ConnectedReadOnly(5),
            SaslAuthenticated(6),
          //會話超時(shí)
            Expired(-112);
.....

(2)WatchedEvent和WatcherEvent

  • zk中使用watchedEvent對象來封裝服務(wù)端事件并傳遞給watcher段磨,從而方便回調(diào)方法process對服務(wù)端事件進(jìn)行處理取逾。
  • WatchedEvent是一個邏輯事件,用于服務(wù)端和客戶端程序執(zhí)行過程中所需要的邏輯對象薇溃,而WatcherEvent可以用于網(wǎng)絡(luò)傳送菌赖。服務(wù)端在生成WatchedEvent事件之后,會調(diào)用getWrapper方法將自己包裝成WatcherEvent沐序,傳送給客戶端,客戶端在接受到服務(wù)端這個事件對象后堕绩,還原為WatchedEvent事件策幼,并傳遞給process方進(jìn)行回處理。
public class WatchedEvent {
//通知狀態(tài)
    private final KeeperState keeperState;
//事件類型
    private final EventType eventType;
//節(jié)點(diǎn)路徑
    private String path;
...
//通過該方法將watchedEvent包裝為watcherEvent
    public WatcherEvent getWrapper() {
        return new WatcherEvent(this.eventType.getIntValue(), 
this.keeperState.getIntValue(), this.path);
    }
}
//實(shí)現(xiàn)了序列化奴紧,可以在網(wǎng)絡(luò)上傳送
public class WatcherEvent implements Record {
    private int type;
    private int state;
    private String path;
...
}

(3)工作機(jī)制


watch工作機(jī)制圖
  • 總體來說watcher工作機(jī)制分為客戶端注冊Watcher特姐、客戶端注冊Watcher、客戶端注冊Watcher三部曲黍氮。

客戶端注冊:

在創(chuàng)建ZK客戶端實(shí)例的時(shí)候唐含,可以向構(gòu)造方法中傳入一個默認(rèn)的Watcher,代表注冊watcher(或者getData,getChildren,Exist三個方法進(jìn)行注冊)。注冊好了之后沫浆,會對該請求request進(jìn)行標(biāo)記捷枯,標(biāo)記為:使用了Watcher監(jiān)聽。然后把Watcher的注冊信息封裝為WatcherRegistration對象专执。然后再封裝為packet對象淮捆,packet可以看做是最小的通信協(xié)議單元,用于進(jìn)行網(wǎng)絡(luò)傳輸本股。隨后攀痊,客戶端就像服務(wù)器端發(fā)送這個請求,同時(shí)等待請求的返回拄显。

服務(wù)端處理Watcher:

ServerCnxn存儲:我們知道ServerCnxn是服務(wù)端與客戶端進(jìn)行網(wǎng)絡(luò)交互的一個接口苟径,代表了客戶端與服務(wù)端的連接。其底層采用netty實(shí)現(xiàn)躬审。所以棘街,在接受到注冊請求之后,服務(wù)端會將ServerCnxn對象和數(shù)據(jù)階段路徑保存到WatchManager的watchTable和watch2Paths中盒件。
Watcher觸發(fā)當(dāng)watcher監(jiān)聽的對應(yīng)的額數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容發(fā)生變更時(shí)候蹬碧。通過調(diào)用WatchManager的triggerWatch方法觸發(fā)相關(guān)的事件。其通過將節(jié)點(diǎn)信息和事件類型進(jìn)行封裝成為watchedEvent炒刁,并查找到到對應(yīng)節(jié)點(diǎn)的注冊的watcher恩沽,然后分別調(diào)用watcher的回調(diào)函數(shù)process。而在process函數(shù)中其實(shí)就是通過封裝的ServerCnxn翔始。但本質(zhì)上并不是客戶端Watcher的真正業(yè)務(wù)邏輯罗心,而是借助當(dāng)前客戶端連接的ServerCnxn對象來實(shí)現(xiàn)對客戶端的WatchedEvent傳遞里伯,真正的客戶端回調(diào)與業(yè)務(wù)邏輯是在客戶端也就是說服務(wù)端在完成watchedEvent封裝后,會通過網(wǎng)絡(luò)傳送給客戶端進(jìn)行處理

客戶端回調(diào)Watcher:

對于服務(wù)器端的響應(yīng)渤闷,客戶端都是由SendThread中的readResponse方法來統(tǒng)一處理的疾瓮。(反序列化、處理chrootPath飒箭、還原為WatchedEvent狼电、回調(diào)Watcher)

(4)小結(jié)

  • watcher的特性總結(jié):

1、一次性:無論是服務(wù)器還是客戶端弦蹂,一旦一個Watcher被觸發(fā)肩碟,就會從相應(yīng)的存儲中移除,這樣的設(shè)計(jì)有利用緩解服務(wù)端的壓力凸椿。但是開發(fā)人員要記住的一點(diǎn)就是反復(fù)注冊削祈!
2、客戶端串行執(zhí)行:客戶端回調(diào)過程是一個串行的過程脑漫,因?yàn)橐WC順序髓抑。
3、輕量:WatchedEvent是ZK整個通知機(jī)制中的最小通知單元优幸,我們說過它只包含三個部分吨拍,通知狀態(tài)、事件類型劈伴、節(jié)點(diǎn)路徑密末。因此它非常的輕量。但是你必要要記住這一點(diǎn)跛璧,它只會告訴客戶端發(fā)生了事件严里,不會說明具體內(nèi)容,你一定要自己重新去主動獲取數(shù)據(jù)追城。另外我們說過刹碾,客戶端注冊Watcher的時(shí)候并不會把真實(shí)的Watcher對象傳遞到服務(wù)器,同時(shí)服務(wù)器端也僅僅是保存了當(dāng)前連接的ServerCnxn對象座柱。因此真的是非常輕量迷帜,網(wǎng)絡(luò)開銷和服務(wù)器內(nèi)存開銷都非常廉價(jià)。

(5)curator客戶端使用watcher

  • curator引入cache來實(shí)現(xiàn)對zk服務(wù)端事件的監(jiān)聽色洞。Cache是curator中對事件監(jiān)聽的包裝戏锹,其對事件的監(jiān)聽可以看成是一個本地緩存視圖與遠(yuǎn)程zk視圖的對比進(jìn)程。同時(shí)curator能夠自動為開發(fā)人員處理反復(fù)注冊監(jiān)聽問題火诸,curator分為兩類節(jié)點(diǎn)的監(jiān)聽:節(jié)點(diǎn)監(jiān)聽和子節(jié)點(diǎn)監(jiān)聽锦针。

NodeCache:用于監(jiān)聽指定zk數(shù)據(jù)節(jié)點(diǎn)本身的變化,定義了事件處理的回調(diào)接口NodeCacheListener,只要數(shù)據(jù)節(jié)點(diǎn)發(fā)生變化(這里的變化不包括刪除后的變化)奈搜,就會回調(diào)該方法悉盆。
PathChildrenCache:用于處理zk數(shù)據(jù)節(jié)點(diǎn)的子節(jié)點(diǎn)變化情況,但是無法觸發(fā)二級子節(jié)點(diǎn)的改變馋吗。

三焕盟、會話

1、會話狀態(tài)
  • zk客戶端與服務(wù)端成功連接后宏粤,就建立起了一個會話脚翘。zk會話在整個運(yùn)行期間的生命周期中,會在不同的會話狀態(tài)之間進(jìn)行切換商架,這些狀態(tài)一般可以分為connecting堰怨、connected、reconneting蛇摸、reconnected、close等灿巧。
2赶袄、會話創(chuàng)建

session實(shí)體:session實(shí)體包含sessionID(會話id,用于標(biāo)識唯一會話)抠藕、timeout(會話超時(shí)時(shí)間)饿肺、ticktime(下次會話超時(shí)時(shí)間)、isclosing(標(biāo)記一個會話是否已經(jīng)關(guān)閉)四個屬性
sessionID:會話id盾似,需要保證其全局唯一性敬辣。

//id為服務(wù)器id(myid文件中的值)
  public static long initializeNextSession(long id) {
//該算法核心是高8位確定所在機(jī)器,后56位使用當(dāng)前時(shí)間的毫秒表示進(jìn)行隨機(jī)
        long nextSid = 0L;
        nextSid = System.currentTimeMillis() << 24 >>> 8;
        nextSid |= id << 56;
        return nextSid;
    }

sessionTracker:是zk的服務(wù)端的會話管理器零院,負(fù)責(zé)會話的創(chuàng)建溉跃、管理和清理工作。

public class SessionTrackerImpl extends ZooKeeperCriticalThread implements SessionTracker {
  //根據(jù)sessionId管理session實(shí)體
    HashMap<Long, SessionTrackerImpl.SessionImpl> sessionsById = new HashMap();
//用于根據(jù)當(dāng)前的會話超時(shí)時(shí)間點(diǎn)來歸檔會話告抄,以便進(jìn)行會話管理和超時(shí)檢驗(yàn)
    HashMap<Long, SessionTrackerImpl.SessionSet> sessionSets = new HashMap();
//根據(jù)sessionId來管理會話的超時(shí)時(shí)間
    ConcurrentHashMap<Long, Integer> sessionsWithTimeout;
...

創(chuàng)建會話:服務(wù)端對于客戶端的請求大致分為四個步驟撰茎,connectionRequest請求、會話創(chuàng)建打洼、處理器鏈路處理龄糊、會話響應(yīng)。在zk中由NIOServerCnxn來負(fù)責(zé)接收來自客戶端的會話創(chuàng)建請求募疮,并反序列化connetRequest請求炫惩,然后根據(jù)zk服務(wù)端的配置來完成會話超時(shí)時(shí)間的協(xié)商。隨后sessionTracker將會為該會話分配一個sessionId阿浓,并將其注冊到sessionsById和sessionWithTimeout中他嚷,同時(shí)進(jìn)行會話的激活。之后,該會話請求會在zk服務(wù)端的各個請求處理器之間進(jìn)行順序流轉(zhuǎn)爸舒,最后完成會話的創(chuàng)建蟋字。

3、會話管理

分桶策略:zk中會話管理由sessionTracker負(fù)責(zé)扭勉,采用“分桶管理策略”鹊奖。就是說將類似的會話放在同一區(qū)塊中進(jìn)行管理,以便于zk對會話進(jìn)行不同區(qū)塊的隔離處理以及同一區(qū)塊的統(tǒng)一處理涂炎。
分桶策略的分配原則是每個會話的下次超時(shí)時(shí)間點(diǎn)ExpirationTime(指的是最近一次可能超時(shí)的事件點(diǎn)忠聚,會話創(chuàng)建完成ExpirationTime=currenTime+sessionTimout),zk的leader服務(wù)器會在運(yùn)行期間定時(shí)的進(jìn)行會話超時(shí)檢查,其時(shí)間間隔是EXpiratiionInterval(默認(rèn)是2000毫秒唱捣,實(shí)際是通過公司計(jì)算出來的)
會話激活:為了保證客戶端的會話有效性两蟀,在zk運(yùn)行過程中,客戶端會在會話超時(shí)時(shí)間內(nèi)向服務(wù)器發(fā)送PING請求來保持會話的有效性震缭,稱為心跳檢查赂毯。同時(shí)服務(wù)端不斷受到客戶端的心跳檢測,并且需要重新激活對應(yīng)的客戶端會話拣宰,這個過程稱為TouchSession党涕。會話激活過程不僅能夠使服務(wù)端檢測到對應(yīng)客戶端的存活性,還可以讓客戶端自己保持連接狀態(tài)巡社。
會話激活四個過程(檢測會話是否關(guān)閉膛堤、計(jì)算該會話的新的超時(shí)時(shí)間、定位該會話當(dāng)前區(qū)塊晌该、遷移會話)肥荔。
會話超時(shí)檢查:sessionTracker中有一個專門的線程用于超時(shí)檢查,其工作機(jī)制就是:逐個依次的對會話桶中剩余的會話進(jìn)行清理
會話清理:sessionTracker的會話超時(shí)檢查線程整理出一些已經(jīng)過期的會話后朝群,就要開始進(jìn)行會話清理了燕耿。

4、會話重連

會出現(xiàn)重連的情況:連接斷開潜圃、會話過期缸棵、會話轉(zhuǎn)移時(shí)候

四、zk中各服務(wù)器角色以及Leader選舉

1谭期、zk各個服務(wù)器角色

leader:是整個zk集群工作機(jī)制中的核心堵第,主要功能(1)事務(wù)請求的唯一調(diào)度和處理者,保證集群事務(wù)處理的順序性(2)集群內(nèi)部各個服務(wù)的調(diào)度者
follower:是zk集群狀態(tài)的跟隨著隧出,主要功能(1)處理客戶端非事物請求踏志,轉(zhuǎn)發(fā)事物請求給leader服務(wù)器(2)參與事物請求proposal的投票(3)參與leader選舉
Observer:與follower唯一區(qū)別是,observer不參加任何形式的投票胀瞪,包括leader選舉和proposal的投票针余。Observer的存在就是在減少投票和選舉中性能影響饲鄙,而達(dá)到集群快速擴(kuò)容的目的。

2圆雁、leader選舉過程

  • leader選舉是zk中最重要技術(shù)之一忍级,也是保證分布式數(shù)據(jù)一致性的關(guān)鍵所在
    服務(wù)啟動時(shí)期的選舉:

1、每一個server發(fā)出一個投票
2伪朽、接收來自各個服務(wù)器的投票
3轴咱、處理投票(zxid大優(yōu)先,myid大的優(yōu)先)
4烈涮、統(tǒng)計(jì)投票
5朴肺、改變服務(wù)器狀態(tài)

運(yùn)行期間的leader選舉(leader掛了后)

1、變更狀態(tài)(oberver變更為LOOKING)
2坚洽、每一個server發(fā)出一個投票
3戈稿、接收來自各個服務(wù)器的投票
4、處理投票(zxid大優(yōu)先讶舰,myid大的優(yōu)先)
5鞍盗、統(tǒng)計(jì)投票
6、改變服務(wù)器狀態(tài)(原子廣播)

3跳昼、選舉算法

略(后續(xù)研究)

五橡疼、數(shù)據(jù)與存儲

  • zk中數(shù)據(jù)存儲分為兩個部分:內(nèi)存數(shù)據(jù)存儲和磁盤數(shù)據(jù)存儲
1、內(nèi)存數(shù)據(jù)存儲
  • zk的數(shù)據(jù)模型是一棵樹庐舟,而這顆樹存儲在內(nèi)存中,包括所有的節(jié)點(diǎn)路徑住拭、節(jié)點(diǎn)數(shù)據(jù)以及ACL信息等挪略,zk會定時(shí)的將這些數(shù)據(jù)存儲到磁盤上。
    DataTree:DataTree是zk內(nèi)存數(shù)據(jù)存儲的核心滔岳,是一個數(shù)的數(shù)據(jù)結(jié)構(gòu)杠娱,代表了內(nèi)存中一份完成的數(shù)據(jù)。
    DataNode:DataNode是數(shù)據(jù)存儲的最小單元谱煤,內(nèi)部出了保存節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容摊求、acl列表和節(jié)點(diǎn)狀態(tài)外,還記錄了基本數(shù)據(jù)結(jié)構(gòu)中的樹的描述
    ZKDatabase:是zk的內(nèi)存數(shù)據(jù)庫刘离,負(fù)責(zé)管理zk的所有會話室叉、DataTree存儲和事物日志,會定期的向磁盤dump快照數(shù)據(jù)硫惕,同時(shí)zk啟動的時(shí)候茧痕,會通過磁盤上的事物日志和快照文件恢復(fù)成一個完成的內(nèi)存數(shù)據(jù)庫。
2恼除、事物日志
  • 配置文件中的dataDir是用于存儲事物日志文件的目錄踪旷。也可以配置dataLogDir為事物日志單獨(dú)分配一個文件存儲目錄。文件存儲時(shí)候都是以ZXID事務(wù)id來命名的。
3令野、snapshot-數(shù)據(jù)快照
  • 數(shù)據(jù)快照是zk數(shù)據(jù)存儲的另一個核心機(jī)制舀患,數(shù)據(jù)快照用來記錄zk服務(wù)器上某一個時(shí)刻的全量內(nèi)存數(shù)據(jù)內(nèi)容,并將其寫入到指定的磁盤文件中气破。

六聊浅、客戶端

客戶端核心組件有:zk實(shí)例、ClientWatchManager(watch管理器)堵幽、HostProvider(客戶端地址列表管理器)和ClientCnxn(客戶端核心線程狗超,主要由SendThread和EventThread構(gòu)成,前者負(fù)責(zé)網(wǎng)絡(luò)通信朴下,后者負(fù)責(zé)事件處理)努咐。客戶端啟動過程:

1殴胧、設(shè)置默認(rèn)的watcher
2渗稍、設(shè)置zk服務(wù)器地址列表
3、創(chuàng)建clientCnxn

七团滥、服務(wù)端

集群版zk服務(wù)端啟動過程:

1竿屹、預(yù)啟動(加載配置文件等)
2、初始化(恢復(fù)本地?cái)?shù)據(jù)等)
3灸姊、leader選舉
4拱燃、leader和follow的交互
5、leader和follow的啟動

八力惯、ACL

  • zk中提供了一套完成的ACL(Access Control List)權(quán)限機(jī)制來保證數(shù)據(jù)的安全碗誉。
  • ACL是訪問控制列表,是一種相對來說比較新穎且更加細(xì)粒度的權(quán)限管理方式父晶,可以針對任意用戶和組件進(jìn)行細(xì)粒度的權(quán)限控制哮缺。通常要理解ACL,要從權(quán)限模式scheme甲喝、授權(quán)對象ID和權(quán)限permission來入手尝苇,通常使用scheme:id:permission來標(biāo)識一個有效的ACL。

參考:《從paxos到zookeeper分布式一致性原理與實(shí)踐》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末埠胖,一起剝皮案震驚了整個濱河市糠溜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌押袍,老刑警劉巖诵冒,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谊惭,居然都是意外死亡汽馋,警方通過查閱死者的電腦和手機(jī)侮东,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豹芯,“玉大人悄雅,你說我怎么就攤上這事√福” “怎么了宽闲?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長握牧。 經(jīng)常有香客問我容诬,道長,這世上最難降的妖魔是什么沿腰? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任览徒,我火速辦了婚禮,結(jié)果婚禮上颂龙,老公的妹妹穿的比我還像新娘习蓬。我一直安慰自己,他們只是感情好措嵌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布躲叼。 她就那樣靜靜地躺著,像睡著了一般企巢。 火紅的嫁衣襯著肌膚如雪枫慷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天浪规,我揣著相機(jī)與錄音流礁,去河邊找鬼。 笑死罗丰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的再姑。 我是一名探鬼主播萌抵,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼元镀!你這毒婦竟也來了绍填?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤栖疑,失蹤者是張志新(化名)和其女友劉穎讨永,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遇革,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卿闹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年揭糕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锻霎。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡著角,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旋恼,到底是詐尸還是另有隱情吏口,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布冰更,位于F島的核電站产徊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蜀细。R本人自食惡果不足惜舟铜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望审葬。 院中可真熱鬧深滚,春花似錦、人聲如沸涣觉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽官册。三九已至生兆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膝宁,已是汗流浹背鸦难。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留员淫,地道東北人合蔽。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像介返,于是被迫代替她去往敵國和親拴事。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355