一篇文章帶你瞭解 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 客戶端是如何進行重連的?segmentfault

ZooKeeper重連

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

Quorum 模式

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

Quorum模式

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

數據一致性socket

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

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

搭建 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 集羣。

相關文章
相關標籤/搜索