一、概述
Zookeeper 是一個開源的分佈式的,爲分佈式應用提供協調服務的 Apache 項目。
Zookeeper 從設計模式角度來理解:是一個基於觀察者模式設計的分佈式服務管理框架,它負責存儲和管理大家都關心的數據,然後接受觀察者的註冊,一旦這些數據的狀態發生變化,Zookeeper 就將負責通知已經在 Zookeeper 上註冊的那些觀察者做出相應的反應,從而實現集羣中類似 Master/Slave 管理模式
Zookeeper=文件系統+通知機制
二、特點
- Zookeeper:一個領導者(leader),多個跟隨者(follower)組成的集羣。
- Leader負責進行投票的發起和決議,更新系統狀態
- Follower用於接收客戶請求並向客戶端返回結果,在選舉 Leader 過程中參與投票
- 集羣中只要有半數以上節點存活,Zookeeper 集羣就能正常服務。
- 全局數據一致:每個 server 保存一份相同的數據副本,client 無論連接到哪個 server,數據都是一致的。
- 更新請求順序進行,來自同一個 client 的更新請求按其發送順序依次執行。
- 數據更新原子性,一次數據更新要麼成功,要麼失敗。
- 實時性,在一定時間範圍內,client 能讀到最新數據。
三、數據結構
ZooKeeper 數據模型的結構與 Unix 文件系統很類似,整體上可以看作是一棵樹,每個節點稱做一個 ZNode。
很顯然 zookeeper 集羣自身維護了一套數據結構。這個存儲結構是一個樹形結構,其上的每一個節點,我們稱之爲"znode",每一個 znode 默認能夠存儲 1MB 的數據,每個 ZNode都可以通過其路徑唯一標識
四、應用場景
提供的服務包括:統一命名服務、統一配置管理、統一集羣管理、服務器節點動態上下線、軟負載均衡等。
統一命名服務
統一配置管理
統一集羣管理
服務器動態上下線
軟負載均衡
五、Zookeeper內部原理
1、選舉機制(面試重點)
1)半數機制(Paxos 協議):集羣中半數以上機器存活,集羣可用。所以 zookeeper適合裝在奇數臺機器上。
2)Zookeeper 雖然在配置文件中並沒有指定 master 和 slave。但是,zookeeper 工作時,是有一個節點爲 leader,其他則爲 follower,Leader 是通過內部的選舉機制臨時產生的
3)以一個簡單的例子來說明整個選舉的過程。
假設有五臺服務器組成的 zookeeper 集羣,它們的 id 從 1-5,同時它們都是最新啓動的,也就是沒有歷史數據,在存放數據量這一點上,都是一樣的。
假設這些服務器依序啓動,來看看會發生什麼。
(1)服務器 1 啓動,此時只有它一臺服務器啓動了,它發出去的報沒有任何響應,所以它的選舉狀態一直是 LOOKING 狀態。
(2)服務器 2 啓動,它與最開始啓動的服務器 1 進行通信,互相交換自己的選舉結果,由於兩者都沒有歷史數據,所以 id 值較大的服務器 2 勝出,但是由於沒有達到超過半數以上的服務器都同意選舉它(這個例子中的半數以上是 3),所以服務器 1、2 還是繼續保持LOOKING 狀態。
(3)服務器 3 啓動,根據前面的理論分析,服務器 3 成爲服務器 1、2、3 中的老大,而與上面不同的是,此時有三臺服務器選舉了它,所以它成爲了這次選舉的 leader。
(4)服務器 4 啓動,根據前面的分析,理論上服務器 4 應該是服務器 1、2、3、4 中最大的,但是由於前面已經有半數以上的服務器選舉了服務器 3,所以它只能接收當小弟的命了。
(5)服務器 5 啓動,同 4 一樣當小弟。
2、節點類型
1)Znode 有兩種類型:
短暫(ephemeral):客戶端和服務器端斷開連接後,創建的節點自己刪除
持久(persistent):客戶端和服務器端斷開連接後,創建的節點不刪除
2)Znode 有四種形式的目錄節點(默認是 persistent )
(1)持久化目錄節點(PERSISTENT)
客戶端與 zookeeper 斷開連接後,該節點依舊存在
(2)持久化順序編號目錄節點(PERSISTENT_SEQUENTIAL)
客戶端與 zookeeper 斷開連接後,該節點依舊存在,只是 Zookeeper 給該節點名稱進行順序編號
(3)臨時目錄節點(EPHEMERAL)
客戶端與 zookeeper 斷開連接後,該節點被刪除
(4)臨時順序編號目錄節點(EPHEMERAL_SEQUENTIAL)
客戶端與 zookeeper 斷開連接後,該節點被刪除,只是 Zookeeper 給該節點名稱進行順序編號
3)創建 znode 時設置順序標識,znode 名稱後會附加一個值,順序號是一個單調遞增的計數
器,由父節點維護
4)在分佈式系統中,順序號可以被用於爲所有的事件進行全局排序,這樣客戶端可以通過順序號推斷事件的順序
3、stat結構體
1) czxid- 引起這個 znode 創建的 zxid,創建節點的事務的 zxid
每次修改 ZooKeeper 狀態都會收到一個 zxid 形式的時間戳,也就是 ZooKeeper 事務 ID。
事務 ID 是 ZooKeeper 中所有修改總的次序。每個修改都有唯一的 zxid,如果 zxid1 小
於 zxid2,那麼 zxid1 在 zxid2 之前發生。
2) ctime - znode 被創建的毫秒數(從 1970 年開始)
3) mzxid - znode 最後更新的 zxid
4) mtime - znode 最後修改的毫秒數(從 1970 年開始)
5) pZxid-znode 最後更新的子節點 zxid
6) cversion - znode 子節點變化號,znode 子節點修改次數7)dataversion - znode 數據變化號
8) aclVersion - znode 訪問控制列表的變化號
9) ephemeralOwner- 如果是臨時節點,這個是 znode 擁有者的 session id。如果不是臨時節
點則是 0。
10) dataLength- znode 的數據長度
11) numChildren - znode 子節點數量
4、監聽器原理(面試重點)
1)監聽原理詳解
1)首先要有一個 main()線程
2)在 main 線程中創建 Zookeeper 客戶端,這時就會創建兩個線程,一個負責網絡連接通信(connet),一個負責監聽(listener)。
3)通過 connect 線程將註冊的監聽事件發送給 Zookeeper。
4)在 Zookeeper 的註冊監聽器列表中將註冊的監聽事件添加到列表中。
5)Zookeeper 監聽到有數據或路徑變化,就會將這個消息發送給 listener 線程。
6)listener 線程內部調用了 process()方法。
2)常見的監聽
(1)監聽節點數據的變化:
get path [watch]
(2)監聽子節點增減的變化
ls path [watch]
5、寫數據流程
客戶端向服務器提交數據,是怎麼寫的?
1)怎麼保證每個節點上的副本都是一樣的?
2)Leader和Follower是怎麼分工的,都做了什麼事情?
ZooKeeper 的寫數據流程主要分爲以下幾步:
1) 比如 Client 向 ZooKeeper 的 Server1 上寫數據,發送一個寫請求。
2) 如果 Server1 不是 Leader,那麼 Server1 會把接受到的請求進一步轉發給 Leader,因爲每個 ZooKeeper 的 Server 裏面有一個是 Leader。這個 Leader 會將寫請求廣播給各個Server,比如 Server1 和 Server2, 各個 Server 寫成功後就會通知 Leader。
3) 當 Leader 收到大多數 Server 數據寫成功了,那麼就說明數據寫成功了。如果這裏三個節點的話,只要有兩個節點數據寫成功了,那麼就認爲數據寫成功了。寫成功之後,Leader 會告訴 Server1 數據寫成功了。
4) Server1 會進一步通知 Client 數據寫成功了,這時就認爲整個寫操作成功。ZooKeeper整個寫數據流程就是這樣的。