Zookeeper 理論總結


 

zk的數據模型

在這裏插入圖片描述
樹結構,/是根節點,節點叫做znode,一個znode對應一個文件目錄。
 

有四種類型的znode

  • PERSISTENT 持久,znode創建後一直保留
  • PERSISTENT_SEQUENTIAL 持久、順序編號
  • EPHEMERAL 臨時,創建znode的zk client斷開與zk server的連接後,zk server會自動刪除該znode
  • EPHEMERAL_SEQUENTIAL 臨時、順序編號

臨時節點常用於實現分佈式鎖。

 

zk server的集羣模式

在這裏插入圖片描述
 

zk server有3種角色

  • leader  負責處理zk client的寫(、讀)請求,一個zk集羣只有一個leader
  • follower  同步leader的數據,負責處理zk client的讀請求,並參與leader的選舉
  • observer  負責處理zk client的讀請求,但不參與leader的選舉

zk集羣是讀寫分離的模式,leader負責寫(也可以處理讀),follower負責讀。

 

有follower就夠了,爲什麼還要使用observer?

1、提高併發負載

observer可以協助 follower 處理更多的讀請求,提高讀請求的吞吐量
 

2、減少選舉的時間花銷

eg. follower5個、observer6個,選舉leader只需要等待3臺機器同意;如果11個全是follower,需要等待6個同意,大大增加了選舉的時間花銷。
 

3、提高集羣可用性

down掉一半集羣不可用,指的是followerdown掉一半,observer不參與數量統計,就算observer全部宕掉,也沒關係。

eg. follower5個、observer8個,down掉所有observer、2個follower總共10個,集羣仍然可用;如果13個全是follower,宕掉7個集羣就不可用,顯然使用observer可用性更高。

 

zk server集羣至少需要3個zk server,爲什麼官方推薦參與集羣的zk server數量爲奇數?

因爲單數、雙數的容災能力一樣,少用一臺機器還可以節約成本。

eg. zk server數量爲5,down掉3個集羣就不可用;數量爲6,還是down3個集羣就不可用。容災能力(可用性)一樣,少用1臺機器還節約了成本。

 

zk的工作原理

zk的核心機制是原子廣播,這個機制保證了zk server之間的數據同步。
 

實現原子廣播的協議是Zab協議,Zab協議有3種模式

  • 恢復模式。leader故障後自動進入恢復模式,將集羣恢復到正常工作狀態。先從follower中選出一個新leader,其它follower從新leader處同步數據,大多數follower完成同步恢復模式就結束了。
  • 同步模式。follower從leader處同步數據。同步模式也是恢復模式的一部分。
  • 廣播模式。leader處理寫請求時,廣播通知follower發起投票,半數以上的follower同意後,leader執行寫請求(修改自身的znode),執行後將修改、更新廣播給follower、observer,完成數據同步。

 

leader的選舉機制

zk server在集羣中的4種狀態

  • LOOKING:leader宕掉了,尚未選出新leader
  • LEADING:當前zk server成爲leader
  • FOLLOWING:當前zk server是follower,同步leader的數據
  • OBSERVING:當前zk server是observer,同步leader的數據

 

相關概念
1、myid

唯一標識集羣中的一個zk server
 

2、zxid
zxid其實是一個ReentranReadWriteLock,爲保證數據一致性,一個節點同一時刻只執行一個讀寫操作,自然要加鎖。follower、observer只是對外不處理寫請求,同步leader數據時依然要同步寫操作。

zxid的前32位表示epoch(紀元、時代),一個leader對應一個epoch(時代),換了新leader,epoch會自動使用新值。

zxid的後32位表示xid,每一個寫操作都是一個事務,xid即事務id。

myid標識的是zkServer節點,zxid標識的是數據版本。
 

3、Logicalclock 邏輯時鐘
邏輯時鐘是選舉時的一個概念,其值就是zxid中epoch的值,標識一個時代。選舉出新的leader,新leader的統治時代就此誕生。

 

leader的選舉時機

  • 集羣啓動還沒有leader時
  • leader宕機時

 

leader的選舉機制、過程

  • 集羣沒有leader,所有zk server都是LOOKING狀態
  • 所有follower都參與投票,投的都是自己,寫上自己的myid、zxid,廣播出去
  • 比較zxid,先選epoch大的(紀元新的);如果有相同的從裏面選xid大的(同步數據多的)。這2項都是爲了保證新leader的數據更齊全。如果還有相同的,選myid大的。
  • 選出新leader後,其它zk server從新leader處同步數據,leader狀態變爲LEADING,follower轉態變爲FOLLOWING,observer狀態變爲OBSERVING。

 

zk server如何處理zk client的請求?

讀請求:所有的zk server都可以處理讀請求,leader收到讀請求也會處理;
寫請求:由leader處理,follower、observer收到寫請求時轉交給leader處理。
 

leader使用paxos算法來處理寫請求

  • leader將寫請求都放到一個隊列中,並給每個寫請求分配唯一的編號,編號從小到大依次遞增,按照先進先出的順序處理

  • 執行某個寫請求時,leader先向follower發起投票,是否要執行這個寫請求,如果超過半數的follower同意,leader就會執行這個寫請求。同一時刻,leader只執行一個寫請求,以保證數據的一致性

  • follower、observer同步數據(寫操作)時,會與前面已同步的寫請求的編號對比,如果編號小於之前已同步的寫請求的編號,說明自己數據同步出了問題,數據不一致了,立刻停止對外服務,從leader同步全量數據。
     

準確來說不是先投票再執行。執行流程:

  • leader直接執行寫請求,執行完後廣播通知follower、observer同步這個寫操作,follower、observer從leader處同步這個寫操作。整個流程作爲一個事務來處理。
  • 如果半數以上follower、observer完成同步(完成寫操作),就提交事務(投票通過);如果在指定時間內完成同步的zk server數量沒達到一半,就回滾這個寫操作(投票失敗)。

其實並不算投票,只是統計指定時間內完成該寫操作同步的zk server數量。

 

zk的特點

  • 順序一致性:zk server使用paxos算法來處理請求,將請求放在隊列中,先進先出,請求的執行順序與發送順序一致。可用此特點實現隊列
  • 數據更新原子性:一次寫操作即一個事務,要麼成功(都應用、同步到所有節點),要麼失敗(所有節點都不使用這次數據更新)
  • 單一視圖: zk client無論連接到哪個zk server,讀到的數據都是相同的
  • 實時性: zk client讀取到的是zk server上最新的數據
  • 高性能:zk server將全量數量存儲在內存中,性能極高,尤其是處理讀請求的時候。處理寫請求(更新znode)時,要把更新從內存同步到文件,同步到follower、observer,性能稍低

 

zk的心跳機制

zk通過心跳機制維護各個zk client的狀態。

zk cli每隔一定時間(默認2000ms)發送一個心跳包給zk server,如果zk server連續多少次(默認10次)沒有收到某個zk cli的心跳包,就認爲該zk cli掛了,自動銷燬對應的session、刪除本次會話中創建的臨時節點。

 

zk的watcher機制

也叫作觀察/通知機制,zk client可以watch某個znode,指定的znode發生改變時,zk server會通知watch了此znode的zk client。

這其實是一種特殊的發佈/訂閱,zk client訂閱znode的改變事件,指定的znode發生改變時zk server發佈消息,訂閱了該znode改變事件的zk client會收到消息。

watcher是觀察者模式的體現,觀察到某種現象發生時自動做一些事情。
 

有2種watcher

# get、stat這2種方式設置的watcher,都只監聽節點本身的數據變化,不監聽子孫節點
get  -w /mall
stat -w /mall


# ls方式設置的watcher只監聽子節點的數量變化,不監聽節點本身的數據變化,也不監聽孫節點
ls -w /mall

watcher是一次性的,觸發1次後就銷燬,如果要繼續監聽,需要重新設置watcher。

 

acl 權限控制

可以給znode設置用戶權限,限制用戶對znode可以進行的操作,提高數據安全性。
 

znode的acl權限

  • c:create,可創建子節點
  • d:delete,可刪除子節點
  • r:read,可讀取節點數據
  • w:write,可寫入|更新節點數據
  • a:admin,可管理此節點,配置acl權限

 

acl權限操作

# 查看指定節點的acl權限設置,默認所有用戶的權限都是cdrwa(全部權限)
getAcl /mall

# 統一設置所有用戶的權限,world:anyone:權限
setAcl world:anyone:cdrw


# 設置某個用戶的權限

# auth:用戶名:密碼:權限
auth:chy:abcd:cdrw

# 或者 digest:用戶名:BASE64(SHA1(密碼)):權限
digest:chy:BASE64(SHA1(abcd)):cdrw

# auth、digest設置的密碼都是以密文方式存儲在zk server上,但驗證密碼時auth是輸入明文、digest是輸入SHA1加密後的密文。
# auth更簡單,digest更安全、但也更麻煩


# 根據ip設置權限
ip:192.168.1.1:cdrw

# 給znode設置用戶權限後,操作該znode時需要驗證用戶名、密碼
addauth digest chy:abcd

 

設置超級用戶
超級用戶具有所有的acl權限,可以操作所有的znode。
 
先在IDEA中獲取密文

//用戶名:密碼,此處設置的用戶名、密碼都是super
String str = DigestAuthenticationProvider.generateDigest("super:super");
System.out.println(str);

 
編輯bin目錄下的zkServer.sh

vim zkServer.sh

# 找到以下代碼
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
    "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \

# 在第二行末尾的\之前加上以下代碼,superDigest=後面是IDEA輸出的密文
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:gG7s8t3oDEtIqF6DM9LlI/R+9Ss="

超級用戶可以管理所有的znode,但如果在設置超級用戶之前,就已創建了某些znode、並手動給這些znode設置了acl權限,則超級用戶對這些之前創建的znode沒有管理權限。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章