Zookeeper是Hadoop的一個子項目,它是分布式系統中的協調系統,可提供的服務主要有:配置服務、名字服務、分布式同步、組服務等。
它有如下的一些特點:
Zookeeper的核心是一個精簡的文件系統,它支持一些簡單的操作和一些抽象操作,例如,排序和通知。
Zookeeper的原語操作是很豐富的,可實現一些協調數據結構和協議。例如,分布式隊列、分布式鎖和一組同級別節點中的“領導者選舉”。
Zookeeper支持集群模式,可以很容易的解決單點故障問題。
不同進程間的交互不需要了解彼此,甚至可以不必同時存在,某進程在zookeeper中留下消息后,該進程結束后其它進程還可以讀這條消息。
Zookeeper實現了一個關于通用協調模式的開源共享存儲庫,能使開發者免于編寫這類通用協議。
解壓然后在zookeeper的conf目錄下創建配置文件zoo.cfg,里面的配置信息可參考統計目錄下的zoo_sample.cfg文件,這里配置為:
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/opt/zookeeper-data/ clientPort=2181
tickTime:指定了ZooKeeper的基本時間單位(以毫秒為單位);
initLimit:指定了啟動zookeeper時,zookeeper實例中的隨從實例同步到領導實例的初始化連接時間限制,超出時間限制則連接失敗(以tickTime為時間單位);
syncLimit:指定了zookeeper正常運行時,主從節點之間同步數據的時間限制,若超過這個時間限制,那么隨從實例將會被丟棄;
dataDir:zookeeper存放數據的目錄;
clientPort:用于連接客戶端的端口。
% zkServer.sh start
檢查ZooKeeper是否正在運行
echo ruok | nc localhost 2181
若是正常運行的話會打印“imok”。
默認情況下,zookeeper是支持本地的jmx監控的。若需要遠程監控zookeeper,則需要進行進行如下配置。
默認的配置有這么一行:
ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMain"
在$JMXLOCALONLY后邊添加jmx的相關參數配置:
ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY -Djava.rmi.server.hostname=192.168.1.8 -Dcom.sun.management.jmxremote.port=1911 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false org.apache.zookeeper.server.quorum.QuorumPeerMain"
這樣就可以遠程監控了,可以用jconsole.exe或jvisualvm.exe等工具對其進行監控。
Zookeeper的數據存儲采用的是結構化存儲,結構化存儲是沒有文件和目錄的概念,里邊的目錄和文件被抽象成了節點(node),zookeeper里可以稱為znode。Znode的層次結構如下圖:
最上邊的是根目錄,下邊分別是不同級別的子目錄。
可使用./zkCli.sh -server localhost來連接到Zookeeper服務上。
使用ls /可查看根節點下有哪些子節點,可以雙擊Tab鍵查看更多命令。
可創建org.apache.zookeeper.ZooKeeper對象來作為zk的客戶端,注意,java api里創建zk客戶端是異步的,為防止在客戶端還未完成創建就被使用的情況,這里可以使用同步計時器,確保zk對象創建完成再被使用。
可以使用zhandle_t指針來表示zk客戶端,可用zookeeper_init方法來創建。可在ZK_HOME\src\c\src\ cli.c查看部分示例代碼。
Nginx是反向代理服務器,也被廣泛的作為負載均衡服務器 ,而ZooKeeper是分布式協調服務框架,有時也被用來做負載均衡,當對系統架構做拓展的時候可以考慮zookeeper+nginx配合來做。
后面會分享更多關于devops和DBA方面的內容,感興趣的朋友可以關注下!!
Apache ZooKeeper 是一個開源的實現高可用的分布式協調服務器。ZooKeeper是一種集中式服務,用于維護配置信息,域名服務,提供分布式同步和集群管理。所有這些服務的種類都被應用在分布式環境中,每一次實施這些都會做很多工作來避免出現bug和競爭條件。
ZooKeeper 允許分布式進程通過共享的分層命名空間相互協調,ZooKeeper命名空間與文件系統很相似,每個命名空間填充了數據節點的注冊信息 - 叫做Znode,這是在 ZooKeeper 中的叫法,Znode 很像我們文件系統中的文件和目錄。ZooKeeper 與典型的文件系統不同,ZooKeeper 數據保存在內存中,這意味著 ZooKeeper 可以實現高吞吐量和低時延。
與它協調的分布式進程一樣,ZooKeeper本身也可以在稱為集群的一組主機上進行復制。
組成 ZooKeeper 服務的單個服務端必須了解彼此。它們維護內存中的狀態、持久性的事務日志和快照。只要大多數服務可用,ZooKeeper 服務就可用。
客戶端可以連接到單個的服務器。客戶端通過連接單個服務器進而維護 TCP 連接,通過連接發送請求,獲取響應,獲取監聽事件以及發送心跳,很像Eureka Server 的功能。如果與單個服務器的連接中斷,客戶端會自動的連接到ZooKeeper Service 中的其他服務器。
ZooKeeper使用時間戳來記錄導致狀態變更的事務性操作,也就是說,一組事務通過時間戳來保證有序性。基于這一特性。ZooKeeper可以實現更加高級的抽象操作,如同步等。
ZooKeeper包括讀寫兩種操作,基于ZooKeeper的分布式應用,如果是讀多寫少的應用場景(讀寫比例大約是10:1),那么讀性能更能夠體現出高效。
ZooKeeper提供的命名空間非常類似于標準文件系統。名稱是由斜杠(/)分隔的路徑元素序列。 ZooKeeper名稱空間中的每個節點都由路徑標識。
ZooKeeper的分層命名空間圖
與標準的文件系統所不同的是,ZooKeeper命名空間中的每個節點都可以包含與之關聯的數據以及子項,這就像一個文件也是目錄的文件系統。ZooKeeper被設計用來存儲分布式數據:狀態信息,配置,定位信息等等。所以每個ZooKeeper 節點能存儲的容量非常小,最大容量為 1MB。我們使用術語 Znode 來表明我們正在談論ZooKeeper數據節點。
Znodes 維護了一個 stat 結構,包括數據變更,ACL更改和時間戳的版本號,用來驗證緩存和同步更新。每一次Znode 的數據發生了變化,版本號的數量就會進行增加。每當客戶端檢索某個znode 數據時,它也會接收該數據的版本。
命名空間下數據存儲的Znode 節點都會以原子性的方式讀寫,也就是保證了原子性。讀取所有Znode 相關聯的節點數據并通過寫的方式替換節點數據。每一個節點都會有一個 訪問控制列表(ACL)的限制來判斷誰可以進行操作。
ZooKeeper 也有臨時節點的概念。只要創建的 Znode 的會話(session)處于活動狀態,就會存在這些臨時節點。當會話結束,臨時節點也就被刪除。
ZooKeeper支持watches的概念。客戶端可以在 Znode 上設置監聽。當 Znode 發生變化時,監聽會被觸發并移除。觸發監聽時,客戶端會收到一個數據包告知 Znode 發生變更。如果客戶端與其中一個 ZooKeeper 服務器之間的連接中斷,則客戶端將收到本地通知。
通常在分布式系統中,構成一個集群中的每一臺機器都有一個自己的角色,最典型的集群模式就是 master/slave (主備模式)。在這種模式中,我們把能夠處理寫操作請求的機器成為 Master ,把所有通過異步復制方式獲取最新數據,并提供讀請求服務的機器成為 Slave 機器。
而 ZooKeeper 沒有采用這種方式,ZooKeeper 引用了 Leader、Follower和 Observer 三個角色。ZooKeeper 集群中的所有機器通過選舉的方式選出一個 Leader,Leader 可以為客戶端提供讀服務和寫服務。除了 Leader 外,集群中還包括了 Follower 和 Observer 。Follower 和 Observer 都能夠提供讀服務,唯一區別在于,Observer 不參與 Leader 的選舉過程,也不寫操作的"過半寫成功"策略,因此 Observer 可以在不影響寫性能的情況下提升集群的讀性能。
Session 指的是客戶端會話,在講解會話之前先來了解一下客戶端連接。客戶端連接指的就是客戶端和服務器之間的一個 TCP長連接,ZooKeeper 對外的端口是 2181,客戶端啟動的時候會與服務器建立一個 TCP 連接,從第一次連接建立開始,客戶端會話的生命周期也就開始了,通過這個連接,客戶端能夠通過心跳檢測與服務器保證有效的會話,也能夠向 ZooKeeper 服務器發送請求并接受響應,同時還能夠通過該連接來接收來自服務器的Watch 事件通知。
ZooKeeper 非常快并且很簡單。但是,由于其開發的目的在于構建更復雜的服務(如同步)的基礎,因此它提供了一系列的保證,這些保證是:
ZooKeeper 設計之初提供了非常簡單的編程接口。作為結果,它支持以下操作:
ZooKeeper Components 展現了ZooKeeper 服務的高級組件。除請求處理器外,構成 ZooKeeper 服務的每個服務器都復制其自己的每個組件的副本。
圖中的 Replicated Database (可復制的數據庫)是一個包含了整個數據樹的內存數據庫。更新將記錄到磁盤以獲得可恢復性,并且寫入在應用到內存數據庫之前會得到序列化。
每一個 ZooKeeper 服務器都為客戶端服務。客戶端只連接到一臺服務器用以提交請求。讀請求由每個服務器數據庫的本地副本提供服務,請求能夠改變服務的狀態,寫請求由"同意協議"進行通過。
作為"同意協議" 的一部分,所有的請求都遵從一個單個的服務,由這個服務來詢問除自己之外其他服務是否可以同意寫請求,而這個單個的服務被稱為Leader。除自己之外其他的服務被稱為follower,它們接收來自Leader 的消息并對消息達成一致。消息傳底層負責替換失敗的 leader 并使 follower 與 leader 進行同步。
ZooKeeper 使用自定義的原子性消息傳遞協議。因為消息傳底層是原子性的,ZooKeeper 能夠保證本地副本永遠不會產生分析或者沖突。當 leader 接收到寫請求時,它會計算系統的狀態以確保寫請求何時應用,并且開啟一個捕獲新狀態的事務。
ZooKeeper 的編程接口非常簡單,但是通過它,你可以實現更高階的操作。
ZooKeeper 旨在提供高性能,但是真的是這樣嗎?ZooKeeper是由雅虎團隊開發。當讀請求遠遠高于寫請求的時候,它的效率很高,因為寫操作涉及同步所有服務器的狀態。(讀取數量超過寫入通常是協調服務的情況。)
ZooKeeper吞吐量作為讀寫比率變化是在具有雙2Ghz Xeon和兩個SATA 15K RPM驅動器的服務器上運行的ZooKeeper版本3.2的吞吐量圖。一個驅動器用作專用的ZooKeeper日志設備。快照已寫入OS驅動器。寫請求是1K寫入,讀取是1K讀取。 “服務器”表示ZooKeeper集合的大小,即構成服務的服務器數量。 大約30個其他服務器用于模擬客戶端。 ZooKeeper集合的配置使得Leader不允許來自客戶端的連接。(此部分來源于翻譯結果)
基準也表明它也是可靠的。 存在錯誤時的可靠性顯示了部署如何響應各種故障。 圖中標記的事件如下:
為了在注入故障時顯示系統隨時間的行為,我們運行了由7臺機器組成的ZooKeeper服務。我們運行與以前相同的飽和度基準,但這次我們將寫入百分比保持在恒定的30%,這是我們預期工作量的保守比率。(此部分來源于翻譯結果)
該圖中有一些重要的觀察結果。 首先,如果follower 失敗并迅速恢復,那么即使失敗,ZooKeeper也能夠維持高吞吐量。 但也許更重要的是,leader 選舉算法允許系統足夠快地恢復以防止吞吐量大幅下降。 在我們的觀察中,ZooKeeper 選擇新 leader 的時間不到200毫秒。 第三,隨著follower 的恢復,ZooKeeper能夠在開始處理請求后再次提高吞吐量。