Zookeeper必須瞭解的基礎

weixin_33670713發表於2017-09-05

[TOC]

1 zookeeper網站

Zookeeper中文網站

Zookeeepr英文官網

以上是zookeeper的學習網站,可以先看中文快速瞭解基礎的概念,再看英文原版,從而保證理解上面經量少的偏差

2 zookeeper的安裝和使用入門

2.1 zookeeper安裝與啟動

1 安裝啟動

在官方網站下載安裝包之後,解壓到喜歡的檔案,在conf目錄下建立一個zoo.cfg 檔案作為配置檔案,內容如下

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181

tickTime: 在zookeeper體系中,以毫秒的為單位的基礎時間單位值。用作心跳檢測和session過期(兩倍的tickTime時間)

dataDir: 儲存目錄

clientPort: 客戶端連線時使用的埠

配置完成之後。執行安裝目錄下bin目錄裡面的 zkServer.sh, 例如:/bin/zkServer.sh start ,啟動服務

2 客戶端連線

執行安裝目錄下的zkCli.sh 指令碼使用命令列連線,bin/zkCli.sh -server 127.0.0.1:2181

連線進入之後,使用help可以看到一些操作命令,例如

`ls /` 檢視根目錄下面的節點
`create` 建立節點,例如 create /zk_test my_test_data ,在根目錄下建立zk_test
`set` 設定節點的值,例如 set /zk_test my_new_test_data
`get` 獲取節點的值, 例如 get /zk_test 
`delete` 刪除節點,例如 delete /zk_testls

在zookeeper裡面,所有的節點都是一個路徑,例如在zk_test下面建立一個test節點,就需要知名路徑,create /zk_test/test test_data,所有操作中path 引數從根目錄開始

2.2 zookeeper主從(replicated zookeeper)

主從模式配置和單點模式基本很相似,只是多加入了幾個配置

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

其中

initLimit: 設定參與的機器(quorum)連線到leader的超時時間,單位為tickTime設定的時間,如上配置 這個時間=2000*5=10000ms=10s

syncLimit: 設定從機器到leader的延時時間上限

server.x 代表伺服器的,其中有一個是master,建議最少使用三臺以上服務,zookeeper和redis有點像,使用選舉的策略,所以,最好是奇數的伺服器數量。 server name後面的兩個埠,前面的埠用來連線follower和leader,當新的leader選出來之後,follower就通過這個埠和leader建立連線。後面的埠是作為leader選舉時候的埠

3 zookeeper

瞭解zookeeper的時候,四個最重要的元素一定要知道 ,資料結構(node/Sate),Session, Watcher, ACL,從這開始,依次來了解這些東西

3.1 zookeeper的資料結構

zookeeper是一個分成的名稱空間(hierarchal name space) ,非常像一個分散式檔案系統。命令空間的每個節點可以有自己的資料和子節點。zookeeper的子節點稱之為znode,znode維護了一個stat的資料結構

3.1.1 zookeeper計時

Zookeeper通過多種方式追蹤計時:

Zxid

每個Zookeeper狀態的變化都以zxid(事務ID)的形式接收到標記。這個暴露了Zookeeper所有變化的總排序。每個變化都會有一個zxid,並且如果zxid1早於zxid2則zxid1一定小於zxid2。

版本號

節點的每個變化都會引起那個節點的版本號的其中之一增加。這三個版本號是version(znode的資料變化版本號),cversion(子目錄的變化版本號),和aversion(訪問控制列表的變化版本號)。

Ticks

當使用多伺服器的Zookeeper時,伺服器使用ticks定義事件的時間,如狀態上傳,會話超時,同事之間的連線超時等等。tick次數只是通過最小的會話超時間接的暴露;如果一個客戶端請求會話超時小於最小的會話超時,伺服器就會告訴客戶端會話超時實際上是最低會話超時時間。

Real time

Zookeeper不使用實時或時鐘時間,除了將時間戳加在znode建立和更新的stat結構上。

3.1.2 stat資料結構

執行 get命令檢視一個節點的時候就可以看到,例如 get /zk_test

my_test_data
cZxid = 0x8
ctime = Fri Jun 23 11:05:38 CST 2017
mZxid = 0x8
mtime = Fri Jun 23 11:05:38 CST 2017
pZxid = 0xa
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0

my_test_data 使我們存放的資料

3.2 zookeeper session

主要是控制會話狀態

下面是官網提供的狀態轉換圖:


4752922-f457dc7a6c9de5d2.jpg
zookeeper sessopn狀體圖

3.3 zookeeper watcher(重點)

3.3.1 什麼事watcher

zookeeper的讀操作,- getData(), getChildren(), and exists() ,都可以設定watcher. zookeeper中關於watch的定義是: 當設定了watch的節點的資料發生了變化的時候,會向客戶端傳送一次(one-time trigger)watch的事件。(a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes)

針對這個定義,有下面三個方面的結論:

  1. 一次觸發:當資料有了變化時將向客戶端傳送一個watch事件。例如,如果一個客戶端用getData("/znode1",true)並且過一會之後/znode1的資料改變或刪除了,客戶端將獲得一個/znode1的watch事件。如果/znode1再次改變,將不會傳送watch事件除非設定了新watch。
  2. 發往客戶端: 這意味著事件發往客戶端,但是可能在成功之前沒到客戶端。Watches是非同步發往watchers。Zookeeper提供一個順序保證:在看到watch事件之前絕不會看到變化。網路延遲或其他因素可能引起客戶端看到watches並在不同時間返回code。關鍵點是不同客戶端看到的是一致性的順序。
  3. 為資料設定watch: 一個節點可以有不同方式改變。它幫助Zookeeper維護兩個watches:data watches和child watches。getData()和exists()設定data watches。getChildren()設定child watches。兩者任選其一,它可以幫助watches根據型別返回。getData()和exists()返回關於節點資料的資訊,然而getChildren()返回children列表。因此,setData()將會觸發znode設定的data watches。一個成功的create()將會觸發一個datawatches和一個父節點的child watch。一個成功的delete()將觸發一個data watch和一個child watch

watch事件型別列表及其觸發方法

  • Created event:
    Enabled with a call to exists.
  • Deleted event:
    Enabled with a call to exists, getData, and getChildren.
  • Changed event:
    Enabled with a call to exists and getData.
  • Child event:
    Enabled with a call to getChildren.

3.3.2 watch作用

zookeeper設定了watch,只要作用是什麼呢

  1. Watches和其他事件、watches和非同步恢復都是有序的。Zookeeper客戶端保證每件事都是有序派發
  2. 當新增的watch的節點改變的了資料的時候,客戶端會先看到watch事件,之後才看到新資料
  3. watch事件的順序是和服務的資料改變的順序是一致的

3.4 zookeeper ACL訪問控制

acl主要是對zookeeper的node做訪問許可權的控制,但是,這個訪問許可權是不遞迴到子元素的,也就是說,給node /test_node 設定的許可權只會影響 /test_node ,不會影響他的子節點。

ACLs由對組成(scheme:expression,permissions)。expression的格式是針對scheme。

3.4.1 ACL 預設的許可權如下:

  • CREATE: you can create a child node (可以建立 子節點)
  • READ: you can get data from a node and list its children.(可以檢視節點資料和列出他的子節點)
  • WRITE: you can set data for a node (可以向節點設定資料)
  • DELETE: you can delete a child node (可以刪除 子節點)
  • ADMIN: you can set permissions (可以設定節點的許可權)

在命令列建立的時候,直接使用cdrwa分別代表 create,delete,read,write,admin許可權

3.4.2 ACL 內建的scheme

Zookeeper有下面的schemes:

world:有單獨的id,anyone,代表任何人, 例如節點得預設許可權 world:anyone:cdrwa
auth:不適用任何id,代表任何授權的使用者。
digest:使用username;password字串生成MD5雜湊作為ACL ID身份。通過傳送username:password明文授權。在ACL裡使用時expression將會是username:base64編碼的SHA1 password摘要。
ip:使用客戶端IP作為ACL ID身份。

設定許可權之後,要想訪問,就要獲得具體許可權。

示例:

  1. 命令列執行就會建立一個節點 /test_node 需要的使用者名稱密碼(fun:123123)登入
create /test_node test_acl_data auth:fun:123123:cdrwa
  1. 檢視許可權 getAcl
[zk: 127.0.0.1:2181(CONNECTED) 5] getAcl /test_node
'digest,'fun:lpYnLtsL5UprZTlY9EGtvYhMZU0=
: cdrwa

上面執行效果發現,auth 帶上id(fun:123123)的時候,會得到效果就是digest的許可權設定scheme,在沒有密碼的情況下執行例如 get 會提示許可權不夠

  1. 授權之後,操作node
    使用 addauth 方式授權
addauth digest fun:123123

之後操作就沒有問題了

關於zookeeper的ACL的總結:

  1. acl的許可權設定是對設定的節點有作用,對子節點沒有遞迴作用效果
  2. 授權和scheme有關係,用什麼scheme授權,新增授權(addauth)就用什麼scheme
  3. addauth授權的生命週期同session週期一致

4 zookeeper 一致性保證

相關文章