一、 zookeeper是什麼

官方說辭:Zookeeper 分散式服務框架是Apache Hadoop 的一個子項目,它主要是用來解決分散式應用中經常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分散式應用配置項的管理等。

好抽象,我們改變一下方式,先看看它都提供了哪些功能,然後再看看使用它的這些功能能做點什麼。

二、 zookeeper提供了什麼

簡單的說,zookeeper=文件系統+通知機制。

1、 文件系統

Zookeeper維護一個類似文件系統的數據結構:

每個子目錄項如 NameService 都被稱作為 znode,和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在於znode是可以存儲數據的。

有四種類型的znode:

  • 1、PERSISTENT-持久化目錄節點

客戶端與zookeeper斷開連接後,該節點依舊存在

  • 2、 PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點

客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號

  • 3、EPHEMERAL-臨時目錄節點

客戶端與zookeeper斷開連接後,該節點被刪除

  • 4、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點

客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號

2、 通知機制

客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。

就這麼簡單,下面我們看看能做點什麼呢?

三、 我們能用zookeeper做什麼

1、 命名服務

這個似乎最簡單,在zookeeper的文件系統裏創建一個目錄,即有唯一的path。在我們使用tborg無法確定上遊程序的部署機器時即可與下遊程序約定好path,通過path即能互相探索發現,不見不散了。

2、 配置管理

程序總是需要配置的,如果程序分散部署在多臺機器上,要逐個改變配置就變得困難。好吧,現在把這些配置全部放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,然後所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然後從 Zookeeper 獲取新的配置信息應用到系統中就好。

3、 集羣管理

所謂集羣管理無在乎兩點:是否有機器退出和加入、選舉master。

對於第一點,所有機器約定在父目錄GroupMembers下創建臨時目錄節點,然後監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,於是,所有人都知道:它上船了。新機器加入也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了。

對於第二點,我們稍微改變一下,所有機器創建臨時順序編號目錄節點,每次選取編號最小的機器作為master就好。

4、 分散式鎖

有了zookeeper的一致性文件系統,鎖的問題變得容易。鎖服務可以分為兩類,一個是保持獨佔,另一個是控制時序。

對於第一類,我們將zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。廁所有言:來也沖沖,去也沖沖,用完刪除掉自己創建的distribute_lock 節點就釋放出鎖。

對於第二類, /distribute_lock 已經預先存在,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除,依次方便。

5、隊列管理

兩種類型的隊列:

  • 1、 同步隊列,當一個隊列的成員都聚齊時,這個隊列纔可用,否則一直等待所有成員到達。
  • 2、隊列按照 FIFO 方式進行入隊和出隊操作。

第一類,在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。

第二類,和分散式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。

終於瞭解完我們能用zookeeper做什麼了,可是作為一個程序員,我們總是想狂熱瞭解zookeeper是如何做到這一點的,單點維護一個文件系統沒有什麼難度,可是如果是一個集羣維護一個文件系統保持數據的一致性就非常困難了。

四、 分散式與數據複製

Zookeeper作為一個集羣提供一致的數據服務,自然,它要在所有機器間做數據複製。數據複製的好處:

1、 容錯

一個節點出錯,不致於讓整個系統停止工作,別的節點可以接管它的工作;

2、提高系統的擴展能力

把負載分佈到多個節點上,或者增加節點來提高系統的負載能力;

3、提高性能

讓客戶端本地訪問就近的節點,提高用戶訪問速度。

從客戶端讀寫訪問的透明度來看,數據複製集羣系統分下面兩種:

  • 1、寫主(WriteMaster) 對數據的修改提交給指定的節點。讀無此限制,可以讀取任何一個節點。這種情況下客戶端需要對讀與寫進行區別,俗稱讀寫分離;
  • 2、寫任意(Write Any)對數據的修改可提交給任意的節點,跟讀一樣。這種情況下,客戶端對集羣節點的角色與變化透明。

對zookeeper來說,它採用的方式是寫任意。通過增加機器,它的讀吞吐能力和響應能力擴展性非常好,而寫,隨著機器的增多吞吐能力肯定下降(這也是它建立observer的原因),而響應能力則取決於具體實現方式,是延遲複製保持最終一致性,還是立即複製快速響應。

我們關注的重點還是在如何保證數據在集羣所有機器的一致性,這就涉及到paxos演算法。

五、 數據一致性與paxos演算法

據說Paxos演算法的難理解與演算法的知名度一樣令人敬仰,所以我們先看如何保持數據的一致性,這裡有個原則就是:

在一個分散式資料庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。

Paxos演算法解決的什麼問題呢,解決的就是保證每個節點執行相同的操作序列。好吧,這還不簡單,master維護一個全局寫隊列,所有寫操作都必須放入這個隊列編號,那麼無論我們寫多少個節點,只要寫操作是按編號來的,就能保證一致性。沒錯,就是這樣,可是如果master掛了呢。

Paxos演算法通過投票來對寫操作進行全局編號,同一時刻,只有一個寫操作被批准,同時並發的寫操作要去爭取選票,只有獲得過半數選票的寫操作才會被批准(所以永遠只會有一個寫操作得到批准),其他的寫操作競爭失敗只好再發起一輪投票,就這樣,在日復一日年復一年的投票中,所有寫操作都被嚴格編號排序。編號嚴格遞增,當一個節點接受了一個編號為100的寫操作,之後又接受到編號為99的寫操作(因為網路延遲等很多不可預見原因),它馬上能意識到自己數據不一致了,自動停止對外服務並重啟同步過程。任何一個節點掛掉都不會影響整個集羣的數據一致性(總2n+1臺,除非掛掉大於n臺)。

總結一下,數據一致性是如何保證的?是投票投出來的~


文末彩蛋

針對於上面涉及到的知識點我總結出了有1到5年開發經驗的程序員在面試中涉及到的絕大部分架構面試題及答案做成了文檔和架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分散式、高並發等架構技術資料),希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習,也可以關注我一下以後會有更多乾貨分享。

喜歡這篇文章的可以點個贊,也可以關注我的專欄 java經驗分享 ,專欄頂部有免費獲取資料方式


推薦閱讀:
相關文章