一篇文章帶你瞭解 ZooKeeper 架構

上一篇文章,咱們講解了 ZooKeeper 入門知識,這篇文章主要講解下 ZooKeeper 的架構,理解 ZooKeeper 的架構能夠幫助咱們更好地設計協同服務。java

首先咱們來看下 ZooKeeper 的整體架構圖。node

ZooKeeper 整體架構

一篇文章帶你瞭解 ZooKeeper 架構

應用使用 ZooKeeper 客戶端庫來使用 ZooKeeper 服務,ZooKeeper 客戶端會和集羣中某一個節點創建 session, ZooKeeper 客戶端負責和 ZooKeeper 集羣的交互。ZooKeeper 集羣能夠有兩種模式:standalone 模式和 quorum 模式。處於 standalone 模式的 ZooKeeper 集羣還有一個獨立運行的 ZooKeeper 節點,standalone 模式通常用來開發。實際生產環境 ZooKeeper 通常處於 quorum 模式,在 quorum 模式下 ZooKeeper 集羣包換多個 ZooKeeper 節點。數據庫

Session

Session 是 ZooKeeper 客戶端的一個重要概念,ZooKeeper 客戶端庫和 ZooKeeper 集羣中的節點建立一個 session。客戶端能夠主動關閉 session。另外若是 ZooKeeper 節點沒有在 session 關聯的 timeout 時間內收到客戶端的數據的話,ZooKeeper 節點也會關閉 session。另外 ZooKeeper 客戶端庫若是發現鏈接的 ZooKeeper 出錯,會自動的和其餘 ZooKeeper 節點創建鏈接。apache

下圖展現了 ZooKeeper 客戶端是如何進行重連的?服務器

一篇文章帶你瞭解 ZooKeeper 架構

剛開始 ZooKeeper 客戶端和 ZooKeeper 集羣中的節點 1 創建的 session,在過了一段時間後,ZooKeeper 節點 1 失敗了,ZooKeeper 客戶端就自動和 ZooKeeper 集羣中的節點 3 從新創建了 session 鏈接。session

Quorum 模式

處於 Quorum 模式的 ZooKeeper 集羣包含多個 ZooKeeper 節點。下圖的 ZooKeeper 集羣有 3 個節點,其中節點 1 是 leader 節點,節點 2 和節點 3 是 follower 節點。集羣中只能有一個 leader 節點,能夠有多個 follower 節點,leader 節點能夠處理讀寫請求,follower 只能夠處理讀請求。follower 在接到寫請求時會把寫請求轉發給 leader 來處理。架構

一篇文章帶你瞭解 ZooKeeper 架構

下面來講下 ZooKeeper 保證的數據一致性:socket

數據一致性ide

  • •可線性化(Linearizable)寫入:先到達 leader 的寫請求會被先處理,leader 決定寫請求的執行順序。
  • •客戶端 FIFO 順序:來自給定客戶端的請求按照發送順序執行。

爲了讓你們更好地理解 Quorum 模式,下面會配置一個 3 節點的 Quorum 模式的 ZooKeeper 集羣。.net

搭建 3 節點 ZooKeeper 集羣

首先須要準備 3 個配置文件,dataDir 和 clientPort 配置項要配置不一樣的值。3 個配置文件的 server.n 部分都是同樣的。在 server.1=127.0.0.1:3333:3334,其中 3333 是 quorum 之間的通訊的端口號,3334 是用於 leader 選舉的端口號。

還須要在每一個節點的 dataDir 目錄下建立 myid 文件,裏面內容爲一個數字,用來標識當前主機,配置文件中配置的 server.n 中 n 爲何數字,則 myid 文件中就輸入這個數字。

以下是第 1 個節點的配置文件,其中目錄是 node1,端口號用的是 2181,另外兩個節點的目錄分別是 node2 和 node3,端口號分別爲 2182 和 2183,最下面的三行都是同樣的:

# 心跳檢查的時間 2秒
tickTime=2000
# 初始化時 鏈接到服務器端的間隔次數,總時間10*2=20秒
initLimit=10
# ZK Leader 和follower 之間通信的次數,總時間5*2=10秒
syncLimit=5
# 存儲內存中數據庫快照的位置,若是不設置參數,更新事務日誌將被存儲到默認位置。
dataDir=/data/zk/quorum/node1
# ZK 服務器端的監聽端口  
clientPort=2181

server.1=127.0.0.1:3333:3334
server.2=127.0.0.1:4444:4445
server.3=127.0.0.1:5555:5556

下面來啓動這個集羣,首先啓動第一個節點,啓動命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node1.cfg

注:start-foreground 選項 zkServer.sh 在前臺運行,把日誌直接打到 console。若是把日誌打到文件的話,這三個 zkServer.sh 會把日誌打到同一個文件。

在啓動第一個節點後日志中會出現以下:

2019-12-29 13:14:35,758 [myid:1] - WARN  [WorkerSender[myid=1]:QuorumCnxManager@679] - Cannot open channel to 2 at election address /127.0.0.1:4445
java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:650)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:707)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:620)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:477)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:456)
    at java.lang.Thread.run(Thread.java:748)

緣由是配置文件中配置的爲 3 個節點,可是隻啓動了 1 個節點,目前他和其餘另外兩個節點創建不了鏈接,因此報這個問題。

接下來啓動第 2 個節點,執行命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node2.cfg

啓動後,咱們能夠在節點 2 的日誌中發現這麼一行:

2019-12-29 13:15:13,699 [myid:2] - INFO  [QuorumPeer[myid=2](plain=/0.0.0.0:2182)(secure=disabled):Leader@464] - LEADING - LEADER ELECTION TOOK - 41 MS

這說明節點 2 成爲了 leader 節點,一樣能夠在節點 1 的日誌中發現以下一行日誌,說明了節點 1 成爲了 follower 節點。

2019-12-29 13:15:13,713 [myid:1] - INFO  [QuorumPeer[myid=1](plain=/0.0.0.0:2181)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 61 MS

由於對於一個三節點集羣來講兩個就表明了多數,就造成了 Quorum 模式,接下來啓動第 3 個節點,執行命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node3.cfg

啓動後在日誌中也有以下一行,說明第 3 個節點也加入這個集羣,而且是做爲 follower 節點加入的。

2019-12-29 13:15:52,440 [myid:3] - INFO  [QuorumPeer[myid=3](plain=/0.0.0.0:2183)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 15 MS

下面來啓動客戶端來使用這個三節點集羣,在命令中加了 -server 選項,後面指定的是三個節點的主機名和端口號,命令以下:

zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
2019-12-29 13:45:44,982 [myid:127.0.0.1:2181] - INFO  [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x101fff740830000, negotiated timeout = 30000

經過啓動日誌能夠看到客戶端和端口號爲 2181 的節點創建了鏈接,也就是和第 1 個節點創建了鏈接。

咱們執行 ls -R / 命令看下這個集羣中的 znode 數據。

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 1] ls -R /
/
/zookeeper
/zookeeper/config
/zookeeper/quota

下面咱們殺掉一個 ZooKeeper 節點,看客戶端是否能進行重連。如今咱們連的節點 1,咱們來把節點 1 殺掉,能夠在客戶端的日誌中發現客戶端和端口號爲 2183 的節點從新創建了鏈接,也就是和節點 3 創建了鏈接。

2019-12-29 14:03:31,392 [myid:127.0.0.1:2183] - INFO  [main-SendThread(127.0.0.1:2183):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2183, sessionid = 0x101fff740830000, negotiated timeout = 30000

而後咱們再看下客戶端可否正常使用,執行 ls -R / ,能夠發現可以正常返回數據,說明客戶端是可以正常使用的。

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 4] ls -R /
/
/zookeeper
/zookeeper/config
/zookeeper/quota

總結

這篇文章主要講解了 ZooKeeper 架構,以及怎樣配置一個三節點的 ZooKeeper 集羣。

●ZooKeeper 入門看這篇就夠了
●Nginx 熱部署和日誌切割,你學會了嗎?
●Nginx 瞭解一下?
●你真的瞭解 volatile 關鍵字嗎?
●Java線程的生老病死
●Java 8 Optional:優雅地避免 NPE

一篇文章帶你瞭解 ZooKeeper 架構

武培軒有幫助?在看,轉發走一波喜歡做者

相關文章
相關標籤/搜索