Zookeeper深入原理

1、系統(tǒng)模型

1.1、數(shù)據(jù)模型

Zookeeper 的視圖結(jié)構(gòu)是一個樹形結(jié)構(gòu)她君,樹上的每個節(jié)點(diǎn)稱之為數(shù)據(jù)節(jié)點(diǎn)(即 ZNode)静稻,每個ZNode 上都可以保存數(shù)據(jù)警没,同時還可以掛載子節(jié)點(diǎn)。并且Zookeeper的根節(jié)點(diǎn)為 "/"振湾。

zookeeper數(shù)據(jù)結(jié)構(gòu).png

1.2杀迹、節(jié)點(diǎn)類型

在 Zookeeper 中,每個數(shù)據(jù)節(jié)點(diǎn)都是有生命周期的押搪,其生命周期的長短取決于數(shù)據(jù)節(jié)點(diǎn)的節(jié)點(diǎn)類型树酪。在 Zookeeper 中有如下幾類節(jié)點(diǎn):

節(jié)點(diǎn)類型 說明
持久節(jié)點(diǎn)(PERSISTENT) 指該數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建后浅碾,就會一直存在于 Zookeeper 服務(wù)器上,直到有刪除操作來主動清除這個節(jié)點(diǎn)续语。
持久順序節(jié)點(diǎn)(PERSISTENT_SEQUENTIAL) 基本特性和持久節(jié)點(diǎn)是一致的垂谢,額外的特性表現(xiàn)在順序性上,在 Zookeeper 中疮茄,每個父節(jié)點(diǎn)都會為它的第一級子節(jié)點(diǎn)維護(hù)一份順序滥朱,用于記錄下每個子節(jié)點(diǎn)創(chuàng)建的先后順序×κ裕基于這個順序特性徙邻,在創(chuàng)建子節(jié)點(diǎn)的時候,可以設(shè)置這個標(biāo)記懂版,那么在創(chuàng)建節(jié)點(diǎn)過程中鹃栽,Zookeeper 會自動為給定節(jié)點(diǎn)名加上一個數(shù)字后綴,作為一個新的躯畴、完整的節(jié)點(diǎn)名民鼓。另外需要注意的是,這個數(shù)字后綴的上限是整型的最大值蓬抄。
臨時節(jié)點(diǎn)(EPHEMERAL) 臨時節(jié)點(diǎn)的生命周期和客戶端的會話綁定在一起丰嘉,如果客戶端會話失效,那么這個節(jié)點(diǎn)就會被自動清理掉嚷缭。另外饮亏,Zookeeper 規(guī)定了不能基于臨時節(jié)點(diǎn)來創(chuàng)建子節(jié)點(diǎn),即臨時節(jié)點(diǎn)只能作為葉子節(jié)點(diǎn)阅爽。
臨時順序節(jié)點(diǎn)(EPHEMERAL_SEQUENTIAL) 基本特性和臨時節(jié)點(diǎn)一致路幸,只是添加了順序的特性。

1.3付翁、狀態(tài)信息

每個數(shù)據(jù)節(jié)點(diǎn)中除了存儲了數(shù)據(jù)內(nèi)容之外简肴,還存儲了數(shù)據(jù)節(jié)點(diǎn)本身的一些狀態(tài)信息(State)。

狀態(tài)屬性 說明
cZxid 即 Create ZXID百侧,表示該數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建時的事務(wù)ID砰识。
ctime 即 Create Time,表示該數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建的時間佣渴。
mZxid 即 Modified ZXID辫狼,表示該節(jié)點(diǎn)最后一次被更新時的事務(wù)ID。
mtime 即 Modified Time辛润,表示該數(shù)據(jù)節(jié)點(diǎn)最后一次被更新的時間膨处。
pZxid 表示該節(jié)點(diǎn)的子節(jié)點(diǎn)列表最后一次被修改時的事務(wù)ID。注意,只有子節(jié)點(diǎn)列表變更了才會變更 pZxid真椿,子節(jié)點(diǎn)內(nèi)容變更不會影響pZxid秦叛。
cversion 表示子節(jié)點(diǎn)的版本號。
dataVersion 表示數(shù)據(jù)節(jié)點(diǎn)的版本號瀑粥。
aclVersion 表示節(jié)點(diǎn)的 ACL 版本號。
ephemeralOwner 創(chuàng)建該臨時節(jié)點(diǎn)的會話的sessionID三圆。如果該節(jié)點(diǎn)是持久節(jié)點(diǎn)狞换,那么這個屬性值為0。
dataLength 表示數(shù)據(jù)內(nèi)容的長度舟肉。
numChildren 表示當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)個數(shù)修噪。

1.4、ZXID

在Zookeeper 中路媚,事務(wù)是指能夠改變 Zookeeper 服務(wù)器狀態(tài)的操作黄琼,我們也稱之為事務(wù)操作或更新操作,一般包括數(shù)據(jù)節(jié)點(diǎn)創(chuàng)建與刪除整慎、數(shù)據(jù)節(jié)點(diǎn)內(nèi)容更新和客戶端會話創(chuàng)建與失效等操作脏款。對于每一個事務(wù)請求,Zookeeper 都會為其分配一個全局唯一的事務(wù)ID裤园,用 ZXID 來表示撤师,通常是一個 64 位的數(shù)字。每一個 ZXID 對應(yīng)一次更新操作拧揽,從這些 ZXID 中可以間接地識別出 Zookeeper 處理這些更新操作請求的全局順序剃盾。

ZXID 是一個 64 位的數(shù)字,其中低 32 位可以看作是一個簡單的單調(diào)遞增的計(jì)數(shù)器淤袜,針對客戶端的每一個事務(wù)請求痒谴,Leader 服務(wù)器在產(chǎn)生一個新的事務(wù) Proposal 的時候,都會對該計(jì)數(shù)器進(jìn)行加 1 操作铡羡;而高 32 位則代表了 Leader 周期 epoch 的編號积蔚,每當(dāng)選舉產(chǎn)生一個新的 Leader 服務(wù)器,就會從這個 Leader 服務(wù)器上取出其本地日志中最大事務(wù) Proposal 的 ZXID蓖墅,并從該 ZXID 中解析出對應(yīng)的 epoch 值库倘,然后再對其進(jìn)行加 1 操作,之后就會以此編號作為新的 epoch论矾,并將低 32 位置 0 來開始生成新的 ZXID教翩。

1.5、版本

Zookeeper 中為數(shù)據(jù)節(jié)點(diǎn)引入了版本的概念贪壳,每個數(shù)據(jù)節(jié)點(diǎn)都具有三種類型的版本信息(在上面的狀態(tài)信息中已經(jīng)介紹了三種版本信息代表的意思)饱亿,對數(shù)據(jù)節(jié)點(diǎn)的任何更新操作都會引起版本號的變化。其中我們以 dataVersion 為例來說明。在一個數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建完畢之后彪笼,節(jié)點(diǎn)的dataVersion 值是 0钻注,表示的含義是 ”當(dāng)前節(jié)點(diǎn)自從創(chuàng)建之后,被更新過 0 次“配猫。如果現(xiàn)在對該節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容進(jìn)行更新操作幅恋,那么隨后,dataVersion 的值就會變成 1泵肄。即表示的是對數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容的變更次數(shù)捆交。

版本的作用是用來實(shí)現(xiàn)樂觀鎖機(jī)制中的 “寫入校驗(yàn)” 的。例如腐巢,當(dāng)要修改數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容時品追,帶上版本號,如果數(shù)據(jù)節(jié)點(diǎn)的版本號與傳入的版本號相等冯丙,就進(jìn)行修改肉瓦,否則修改失敗。

1.6胃惜、Watcher

1.6.1泞莉、概述

Zookeeper 提供了分布式數(shù)據(jù)的發(fā)布/訂閱功能。一個典型的發(fā)布/訂閱模型系統(tǒng)定義了一種一對多的訂閱關(guān)系蛹疯,能夠讓多個訂閱者同時監(jiān)聽某一個主題對象戒财,當(dāng)這個主題對象自身狀態(tài)變化時,會通知所有訂閱者捺弦,使它們能夠做出相應(yīng)的處理饮寞。在 Zookeeper 中,引入了 Watcher 機(jī)制來實(shí)現(xiàn)這種分布式的通知功能列吼。Zookeeper 允許客戶端向服務(wù)端注冊一個 Watcher 監(jiān)聽幽崩,當(dāng)服務(wù)端的一些指定事件觸發(fā)了這個 Watcher,那么就會向指定客戶端發(fā)送一個事件通知來實(shí)現(xiàn)分布式的通知功能寞钥。

Watcher.png

從上圖可以看出 Zookeeper 的 Watcher 機(jī)制主要包括客戶端線程慌申、客戶端WatchMananger 和 Zookeeper 服務(wù)器三部分。在具體工作流程上理郑,簡單地講蹄溉,客戶端在向 Zookeeper 服務(wù)器注冊 Watcher 的同時,會將 Watcher 對象存儲在客戶端的 WatchMananger 中您炉。當(dāng) Zookeeper 服務(wù)器端觸發(fā) Watcher 事件后柒爵,會向客戶端發(fā)送通知,客戶端線程從 WatchManager 中取出對應(yīng)的 Watcher 對象來執(zhí)行回調(diào)邏輯赚爵。

1.6.2棉胀、Watcher特性
  • 一次性:表示無論是服務(wù)端還是客戶端法瑟,一旦一個 Watcher 被觸發(fā),Zookeeper 都會將其從相應(yīng)的存儲中移除唁奢。因此霎挟,開發(fā)人員在 Watcher 的使用上要記住的一點(diǎn)是需要反復(fù)注冊。
  • 客戶端串行執(zhí)行:客戶端 Watcher 回調(diào)的過程是一個串行同步的過程麻掸,這為我們保證了順序酥夭,同時,需要開發(fā)人員注意的一點(diǎn)是脊奋,千萬不要因?yàn)橐粋€ Watcher 的處理邏輯影響了整個客戶端的 Watcher 回調(diào)采郎。
  • 輕量:WatchedEvent 是 Zookeeper 整個 Watcher 通知機(jī)制的最小通知單元,這個數(shù)據(jù)結(jié)構(gòu)中只包含三部分內(nèi)容:通知狀態(tài)狂魔、事件類型和節(jié)點(diǎn)路徑。也就是說淫痰,Watcher通知非常簡單最楷,只會告訴客戶端發(fā)生了事件,而不會說明事件的具體內(nèi)容待错。
1.6.3籽孙、watcher接口設(shè)計(jì)

Watcher是一個接口,任何實(shí)現(xiàn)了Watcher接口的類就是一個新的Watcher火俄。Watcher內(nèi)部包含了兩個枚舉類:KeeperState犯建、EventType

  • Watcher通知狀態(tài)(KeeperState)

    KeeperState是客戶端與服務(wù)端連接狀態(tài)發(fā)生變化時對應(yīng)的通知類型。路徑為org.apache.zookeeper.Watcher.Event.KeeperState瓜客,是一個枚舉類适瓦,其枚舉屬性如下:

枚舉屬性 說明
SyncConnected 客戶端與服務(wù)器正常連接時
Disconnected 客戶端與服務(wù)器斷開連接時
Expired 會話session失效時
AuthFailed 身份認(rèn)證失敗時
  • Watcher事件類型(EventType)

    EventType是數(shù)據(jù)節(jié)點(diǎn)(znode)發(fā)生變化時對應(yīng)的通知類型。EventType變化時KeeperState永遠(yuǎn)處于SyncConnected通知狀態(tài)下谱仪;當(dāng)KeeperState發(fā)生變化時玻熙,EventType永遠(yuǎn)為None。其路徑為org.apache.zookeeper.Watcher.Event.EventType疯攒,是一個枚舉類嗦随,枚舉屬性如下:

枚舉屬性 說明
None
NodeCreated Watcher監(jiān)聽的數(shù)據(jù)節(jié)點(diǎn)被創(chuàng)建時
NodeDeleted Watcher監(jiān)聽的數(shù)據(jù)節(jié)點(diǎn)被刪除時
NodeDataChanged Watcher監(jiān)聽的數(shù)據(jù)節(jié)點(diǎn)內(nèi)容發(fā)生變更時(無論內(nèi)容數(shù)據(jù)是否變化)
NodeChildrenChanged Watcher監(jiān)聽的數(shù)據(jù)節(jié)點(diǎn)的子節(jié)點(diǎn)列表發(fā)生變更時

:客戶端接收到的相關(guān)事件通知中只包含狀態(tài)及類型等信息,不包括節(jié)點(diǎn)變化前后的具體內(nèi)容敬尺,變化前的數(shù)據(jù)需業(yè)務(wù)自身存儲枚尼,變化后的數(shù)據(jù)需調(diào)用get等方法重新獲取砂吞;

1.6.4署恍、捕獲相應(yīng)的事件

上面講到zookeeper客戶端連接的狀態(tài)和zookeeper對znode節(jié)點(diǎn)監(jiān)聽的事件類型,下面我們來講解如何建立zookeeper的watcher監(jiān)聽呜舒。在zookeeper中采用zk.getChildren(path, watch)锭汛、zk.exists(path, watch)笨奠、zk.getData(path, watcher, stat)這樣的方式為某個znode注冊監(jiān)聽。

下表以node-x節(jié)點(diǎn)為例唤殴,說明調(diào)用的注冊方法和可監(jiān)聽事件間的關(guān)系:

注冊方式 Created ChildrenChanged Changed Deleted
zk.exists(“/node-x”,watcher) 可監(jiān)控 可監(jiān)控 可監(jiān)控
zk.getData(“/node-x”,watcher) 可監(jiān)控 可監(jiān)控
zk.getChildren(“/node-x”,watcher) 可監(jiān)控 可監(jiān)控

1.7般婆、ACL

Zookeeper 中提供了一套完善的 ACL(Access Control List)權(quán)限控制機(jī)制來保障數(shù)據(jù)的安全。

1.7.1朵逝、概述

ACL 由三部分組成蔚袍,分別是:權(quán)限模式(Scheme)、授權(quán)對象(ID)和權(quán)限(Permission)配名,通常使用“scheme: ?id:permission”來標(biāo)識一個有效的ACL 信息啤咽。下面分別介紹:

  1. 權(quán)限模式(Scheme)

    方案 說明
    world 只有一個用戶:anyone,代表登錄 Zookeeper 所有人(默認(rèn))
    ip 對客戶端使用IP地址認(rèn)證渠脉。
    auth 使用已添加認(rèn)證的用戶認(rèn)證宇整。
    digest 使用“用戶名:密碼”方式認(rèn)證。
  1. 授權(quán)對象(ID)

    授權(quán)對象ID是指芋膘,權(quán)限賦予的實(shí)體鳞青,例如:IP 地址或用戶。

  1. 權(quán)限(Permission)

    權(quán)限 ACL簡寫 描述
    create c 可以創(chuàng)建子節(jié)點(diǎn)为朋。
    delete d 可以刪除子節(jié)點(diǎn)(僅下一級節(jié)點(diǎn))臂拓。
    read r 可以讀取節(jié)點(diǎn)數(shù)據(jù)或子節(jié)點(diǎn)列表。
    write w 可以對節(jié)點(diǎn)進(jìn)行更新操作习寸。
    admin a 可以設(shè)置節(jié)點(diǎn)訪問控制列表權(quán)限胶惰。
1.7.2、特性
  • zooKeeper的權(quán)限控制是基于每個znode節(jié)點(diǎn)的霞溪,需要對每個節(jié)點(diǎn)設(shè)置權(quán)限孵滞。
  • 每個znode支持設(shè)置多種權(quán)限控制方案和多個權(quán)限。
  • 子節(jié)點(diǎn)不會繼承父節(jié)點(diǎn)的權(quán)限鸯匹,客戶端無權(quán)訪問某節(jié)點(diǎn)剃斧,但可能可以訪問它的子節(jié)點(diǎn)。
1.7.3忽你、案例
  • world授權(quán)模式

    命令

    setAcl <path> world:anyone:<acl>
    

    案例

    [zk: localhost:2181(CONNECTED) 0] create /node1 "node1"
    Created /node1
    [zk: localhost:2181(CONNECTED) 1] getAcl /node1
    'world,'anyone
    : cdrwa
    [zk: localhost:2181(CONNECTED) 2] setAcl /node1 world:anyone:crwa
    cZxid = 0x100000004
    ctime = Fri May 29 14:31:54 CST 2020
    mZxid = 0x100000004
    mtime = Fri May 29 14:31:54 CST 2020
    pZxid = 0x100000004
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    
  • IP授權(quán)模式

    命令

    setAcl <path> ip:<ip>:<acl>
    

    案例

    注意:遠(yuǎn)程登錄zookeeper命令:./zkCli.sh -server ip

    [zk: localhost:2181(CONNECTED) 18] create /node2 "node2"
    Created /node2
    
    [zk: localhost:2181(CONNECTED) 23] setAcl /node2 ip:192.168.150.101:cdrwa
    cZxid = 0xe
    ctime = Fri Dec 13 22:30:29 CST 2019
    mZxid = 0x10
    mtime = Fri Dec 13 22:33:36 CST 2019
    pZxid = 0xe
    cversion = 0
    dataVersion = 2
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 20
    numChildren = 0
    
    [zk: localhost:2181(CONNECTED) 25] getAcl /node2
    'ip,'192.168.150.101
    : cdrwa
    
    #使用IP非 192.168.150.101 的機(jī)器
    [zk: localhost:2181(CONNECTED) 0] get /node2
    Authentication is not valid : /node2 #沒有權(quán)限
    
  • Auth授權(quán)模式

    命令

    addauth digest <user>:<password> #添加認(rèn)證用戶
    setAcl <path> auth:<user>:<acl>
    

    案例

    [zk: localhost:2181(CONNECTED) 6] create /node3 "node3"
    Created /node3
    
    #添加認(rèn)證用戶
    [zk: localhost:2181(CONNECTED) 7] addauth digest ld:123456
    
    [zk: localhost:2181(CONNECTED) 8] setAcl /node3 auth:ld:cdrwa
    cZxid = 0x10000000c
    ctime = Fri May 29 14:47:13 CST 2020
    mZxid = 0x10000000c
    mtime = Fri May 29 14:47:13 CST 2020
    pZxid = 0x10000000c
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    
    [zk: localhost:2181(CONNECTED) 9] getAcl /node3
    'digest,'ld:kesl2p6Yx58a+/mP+TKSFZkzkZ0=
    : cdrwa
    
    #添加認(rèn)證用戶后可以訪問
    [zk: localhost:2181(CONNECTED) 10] get /node3
    node3
    cZxid = 0x10000000c
    ctime = Fri May 29 14:47:13 CST 2020
    mZxid = 0x10000000c
    mtime = Fri May 29 14:47:13 CST 2020
    pZxid = 0x10000000c
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    
  • Digest授權(quán)模式

    命令

    setAcl <path> digest:<user>:<password>:<acl>
    

    這里的密碼是經(jīng)過SHA1及BASE64處理的密文幼东,在SHELL中可以通過以下命令計(jì)算:

    echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
    

    先來計(jì)算一個密文

    echo -n monkey:123456 | openssl dgst -binary -sha1 | openssl base64
    

    案例

    [zk: localhost:2181(CONNECTED) 12] create /node4 "node4"
    Created /node4
    
    [zk: localhost:2181(CONNECTED) 13] setAcl /node4 digest:monkey:Rk6u/zJJdOYrTZ6+J0p4/4gTILg=:cdrwa
    cZxid = 0x10000000e
    ctime = Fri May 29 14:52:50 CST 2020
    mZxid = 0x10000000e
    mtime = Fri May 29 14:52:50 CST 2020
    pZxid = 0x10000000e
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    
    #沒有權(quán)限無法讀取
    [zk: localhost:2181(CONNECTED) 14] getAcl /node4
    Authentication is not valid : /node4
    
    #添加認(rèn)證用戶
    [zk: localhost:2181(CONNECTED) 15] addauth digest monkey:123456
    
    [zk: localhost:2181(CONNECTED) 16] getAcl /node4               
    'digest,'monkey:Rk6u/zJJdOYrTZ6+J0p4/4gTILg=
    : cdrwa
    
    [zk: localhost:2181(CONNECTED) 17] get /node4
    node4
    cZxid = 0x10000000e
    ctime = Fri May 29 14:52:50 CST 2020
    mZxid = 0x10000000e
    mtime = Fri May 29 14:52:50 CST 2020
    pZxid = 0x10000000e
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    
  • 多種模式授權(quán)

    同一個節(jié)點(diǎn)可以同時使用多種模式授權(quán)

    [zk: localhost:2181(CONNECTED) 18] create /node5 "node5"
    Created /node5
    [zk: localhost:2181(CONNECTED) 19] addauth digest ld:123456
    [zk: localhost:2181(CONNECTED) 20] setAcl /node5 ip:192.168.150.101:cdrwa,auth:ld:cdrwa
    cZxid = 0x100000010
    ctime = Fri May 29 14:56:38 CST 2020
    mZxid = 0x100000010
    mtime = Fri May 29 14:56:38 CST 2020
    pZxid = 0x100000010
    cversion = 0
    dataVersion = 0
    aclVersion = 1
    ephemeralOwner = 0x0
    dataLength = 5
    numChildren = 0
    

1.7.4、ACL 超級管理員

zookeeper的權(quán)限管理模式有一種叫做super科雳,該模式提供一個超管可以方便的訪問任何權(quán)限的節(jié)點(diǎn)

假設(shè)這個超管是:super:admin根蟹,需要先為超管生成密碼的密文

echo -n super:admin | openssl dgst -binary -sha1 | openssl base64

那么打開zookeeper目錄下的/bin/zkServer.sh服務(wù)器腳本文件,找到如下一行:

nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"

這就是腳本中啟動zookeeper的命令糟秘,默認(rèn)只有以上兩個配置項(xiàng)简逮,我們需要加一個超管的配置項(xiàng)

"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="

那么修改以后這條完整命令變成了

nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="\
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

之后啟動zookeeper,輸入如下命令添加權(quán)限

addauth digest super:admin #添加認(rèn)證用戶

2、Leader 選舉

2.1尿赚、服務(wù)器狀態(tài)

  • looking:尋找leader狀態(tài)散庶。當(dāng)服務(wù)器處于該狀態(tài)時蕉堰,它會認(rèn)為當(dāng)前集群中沒有Leader,因此需要進(jìn)入 Leader 選舉流程悲龟。
  • leading:領(lǐng)導(dǎo)者狀態(tài)屋讶。表明當(dāng)前服務(wù)器角色是leader。
  • following:跟隨者狀態(tài)须教。表明當(dāng)前服務(wù)器角色是follower皿渗。
  • observing:觀察者狀態(tài)。表明當(dāng)前服務(wù)器角色是observer轻腺。

2.2乐疆、服務(wù)器啟動時期的 Leader 選舉

在服務(wù)器集群初始化階段,我們以 3 臺機(jī)器組成的服務(wù)器集群為例贬养,當(dāng)有一臺服務(wù)器server1 啟動的時候挤土,它是無法進(jìn)行 Leader 選舉的,當(dāng)?shù)诙_機(jī)器 server2 也啟動時误算,此時這兩臺服務(wù)器已經(jīng)能夠進(jìn)行互相通信耕挨,每臺機(jī)器都試圖找到一個 Leader,于是便進(jìn)入了 Leader 選舉流程尉桩。

  1. 每個server發(fā)出一個投票。由于是初始情況贪庙,server1和server2都會將自己作為leader服務(wù)器來進(jìn)行投票蜘犁,每次投票會包含所推舉的服務(wù)器的myid和zxid,使用(myid, zxid)來表示止邮,此時server1的投票為(1, 0)这橙,server2的投票為(2, 0),然后各自將這個投票發(fā)給集群中其他機(jī)器导披。

  2. 集群中的每臺服務(wù)器接收來自集群中各個服務(wù)器的投票屈扎。

  3. 處理投票。針對每一個投票撩匕,服務(wù)器都需要將別人的投票和自己的投票進(jìn)行pk鹰晨,pk規(guī)則如下

    • 優(yōu)先檢查zxid。zxid比較大的服務(wù)器優(yōu)先作為leader止毕。
    • 如果zxid相同模蜡,那么就比較myid。myid較大的服務(wù)器作為leader服務(wù)器扁凛。

    ? 對于Server1而言忍疾,它的投票是(1, 0),接收Server2的投票為(2, 0)谨朝,首先會比較兩者的zxid卤妒,均為0甥绿,再比較myid,此時server2的myid最大则披,于是更新自己的投票為(2, 0)共缕,然后重新投票,對于server2而言收叶,其無須更新自己的投票骄呼,只是再次向集群中所有機(jī)器發(fā)出上一次投票信息即可。

  4. 統(tǒng)計(jì)投票判没。每次投票后蜓萄,服務(wù)器都會統(tǒng)計(jì)投票信息,判斷是否已經(jīng)有過半機(jī)器接受到相同的投票信息澄峰,對于server1嫉沽、server2而言,都統(tǒng)計(jì)出集群中已經(jīng)有兩臺機(jī)器接受了(2, 0)的投票信息俏竞,此時便認(rèn)為已經(jīng)選出了leader绸硕。

  5. 改變服務(wù)器狀態(tài)。一旦確定了leader魂毁,每個服務(wù)器就會更新自己的狀態(tài)玻佩,如果是follower,那么就變更為following席楚,如果是leader咬崔,就變更為leading。

2.3烦秩、服務(wù)器運(yùn)行時期的 Leader 選舉

在zookeeper運(yùn)行期間垮斯,leader與非leader服務(wù)器各司其職,即便當(dāng)有非leader服務(wù)器宕機(jī)或新加入只祠,此時也不會影響leader兜蠕,但是一旦leader服務(wù)器掛了,那么整個集群將暫停對外服務(wù)抛寝,進(jìn)入新一輪leader選舉熊杨,其過程和啟動時期的Leader選舉過程基本一致。

假設(shè)正在運(yùn)行的有server1盗舰、server2猴凹、server3三臺服務(wù)器,當(dāng)前l(fā)eader是server2岭皂,若某一時刻leader掛了郊霎,此時便開始Leader選舉。選舉過程如下:

  1. 變更狀態(tài)爷绘。leader掛后书劝,余下的非 Observer 服務(wù)器都會將自己的服務(wù)器狀態(tài)變更為looking进倍,然后開始進(jìn)入leader選舉過程。
  2. 每個server會發(fā)出一個投票购对。在運(yùn)行期間猾昆,每個服務(wù)器上的zxid可能不同,此時假定server1的zxid為123骡苞,server3的zxid為122垂蜗,在第一輪投票中,server1和server3都會投自己解幽,產(chǎn)生投票(1, 123)贴见,(3, 122),然后各自將投票發(fā)送給集群中所有機(jī)器躲株。
  3. 接收來自各個服務(wù)器的投票片部。
  4. 處理投票。對于投票的處理霜定,和上面提到的服務(wù)器啟動期間的處理規(guī)則是一致的档悠。在這個例子里面,由于 Server1 的 zxid 為 123望浩,Server3 的 zxid 為 122辖所,那么顯然,Server1 會成為 Leader磨德。
  5. 統(tǒng)計(jì)投票缘回。
  6. 改變服務(wù)器狀態(tài)。

2.4剖张、Observer 角色及其設(shè)置

observer角色特點(diǎn):

  1. 不參與集群的leader選舉
  2. 不參與集群中寫數(shù)據(jù)時的ack反饋

為了使用observer角色,在任何想變成observer角色的配置文件中加入如下配置:

peerType=observer

并在所有server的配置文件中揩环,配置成observer模式的server的那行配置追加:observer搔弄,例如:

server.3=192.168.60.130:2289:3389:observer
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丰滑,隨后出現(xiàn)的幾起案子顾犹,更是在濱河造成了極大的恐慌,老刑警劉巖褒墨,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炫刷,死亡現(xiàn)場離奇詭異,居然都是意外死亡郁妈,警方通過查閱死者的電腦和手機(jī)浑玛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來噩咪,“玉大人顾彰,你說我怎么就攤上這事极阅。” “怎么了涨享?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵筋搏,是天一觀的道長。 經(jīng)常有香客問我厕隧,道長奔脐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任吁讨,我火速辦了婚禮髓迎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挡爵。我一直安慰自己竖般,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布茶鹃。 她就那樣靜靜地躺著涣雕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闭翩。 梳的紋絲不亂的頭發(fā)上挣郭,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音疗韵,去河邊找鬼兑障。 笑死,一個胖子當(dāng)著我的面吹牛蕉汪,可吹牛的內(nèi)容都是我干的流译。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼者疤,長吁一口氣:“原來是場噩夢啊……” “哼福澡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起驹马,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤革砸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糯累,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算利,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年泳姐,在試婚紗的時候發(fā)現(xiàn)自己被綠了效拭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖允耿,靈堂內(nèi)的尸體忽然破棺而出借笙,到底是詐尸還是另有隱情,我是刑警寧澤较锡,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布业稼,位于F島的核電站,受9級特大地震影響蚂蕴,放射性物質(zhì)發(fā)生泄漏低散。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一骡楼、第九天 我趴在偏房一處隱蔽的房頂上張望熔号。 院中可真熱鬧,春花似錦鸟整、人聲如沸引镊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弟头。三九已至,卻和暖如春涉茧,著一層夾襖步出監(jiān)牢的瞬間赴恨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工伴栓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伦连,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓钳垮,卻偏偏與公主長得像惑淳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饺窿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容