ZooKeeper 01 - 什么是ZooKeeper + 部署ZooKeeper集群


1 什么是ZooKeeper

ZooKeeper直譯就是動物園管理員, 它是用來管Hadoop(大象)、Hive(蜜蜂)、Pig(小豬)等的管理員(這些都是Apache軟件基金組織旗下大數據方面的技術框架), Apache Hbase和Apache Solr的分布式集群都用到了ZooKeeper.

(1) 百度百科中的說明:

ZooKeeper是一個高可用、分布式的程序協調服務, 是Google的Chubby一個開源的實現, 是Hadoop和Hbase的重要組件.

它是一個為分布式應用提供一致性服務的軟件, 提供的功能包括: 配置維護、域名服務、分布式同步、組服務等.

ZooKeeper的目標就是封裝好復雜易出錯的關鍵服務, 將簡單易用的接口和性能高效、功能穩定的系統提供給用戶.

(2) ZooKeeper的基本運轉流程:

① 選舉Leader;
② 同步數據;
③ 選舉Leader過程中算法有很多, 但要達到的選舉標准是一致的;
④ Leader要具有最高的執行ID, 類似root權限;
⑤ 集群中大多數的機器得到響應並接受選出的Leader.

2 ZooKeeper的功能

2.1 配置管理

項目開發中大多會涉及到各種配置信息, 比如JDBC的連接信息等. 一般將這些信息配置到特定的文件中, 在代碼中引入相關配置文件即可.

—— 這是單服務器應用中常用的做法. 當應用很大、配置文件很多, 尤其是在分布式項目中, 多台服務器的配置需要保持一致, 而如果配置信息會被頻繁地修改, 這個時候還使用配置文件就不是個好主意了.

—— 你總不能手動逐個修改吧? 不僅重復性勞動太多, 而且出錯的可能性更大, 后期維護成本太大.

這種情況下往往需要尋找一種集中管理配置的方法 —— 在這個集中的地方修改了配置, 所有對該配置有依賴的服務都可以獲得變更.

需要考慮的是, 由於多台服務器上的項目都依賴了這個配置, 為了應用的可靠運行, 需要這個集中提供配置服務的應用具備非常高的可靠性.

基於上述分析, 我們可以通過集群來提供配置服務, 保證系統的可靠性. 此時遺留的問題是, 如何保證配置在集群中的一致性呢?

為了提供這種一致性, 前輩們提出了一致性協議, 實現此協議的服務就有ZooKeeper —— 它使用Zab這種一致性協議來保證一致性.

應用場景:
○ HBase中, 客戶端就是連接一個ZooKeeper, 它獲得HBase集群的必要配置信息, 然后才可以進一步操作.
○ 開源消息隊列Kafka中, 使用ZooKeeper來維護broker的信息.
○ Alibaba開源的SOA框架Dubbo中廣泛使用ZooKeeper管理配置信息, 實現服務治理.

2.2 命名服務

場景: 為了通過網絡訪問一個系統, 我們需要知道對方的IP地址, 但由於IP地址是一串數字, 難以記憶, 對用戶並不友好. 這時人們想出通過域名來訪問指定的IP地址.

但計算機並不能識別域名. 為了解決這一問題, 設計者們提出了在每台電腦中都存儲一份"域名到IP地址的映射"的方案. 問題又來了, 如果域名對應的IP地址發生了變化, 又該如何映射呢?

前輩們又設計了DNS(Domain Name System, 域名系統). 我們只需要先訪問一個所有機器都知道的(known)的節點, DNS通過該節點告訴我們當前訪問的域名對應的IP地址是什么. 也就是DNS提供統一的訪問接口.

在應用開發中也會存在這類問題, 特別是應用中存在大量服務時, 如果我們將服務的地址保存在本地, 其他用戶是不好獲取這些地址並訪問的. 但是如果我們為用戶提供統一的入口, 在本地對各種用戶請求作相應的映射處理, 就可以解決此類問題.

2.3 分布式鎖

ZooKeeper是一個分布式協調服務, 我們可以利用ZooKeeper來協調多個分布式進程之間的活動.

比如在一個分布式環境中, 為提高系統的可靠性, 集群中的每台服務器都部署了相同的服務.

這些相同的服務都要執行相同的任務, 為了保證數據的一致性, 集群之間就要互相協調, 常規的編程方案解決協調問題是非常復雜繁瑣的.

通常的做法是: 使用分布式鎖, 在某個時刻只有一個服務在工作, 當這台服務出了問題鎖就立即釋放, 並 fail over 到其他服務. 這種設計被稱作叫Leader Election (leader選舉). 比如HBase的Master就采用了這種機制.

注意: 分布式鎖與進程鎖是有區別的, 使用時要更加謹慎.

2.4 集群管理

在分布式集群應用中, 存在諸如軟硬件故障、斷電、網絡等問題, 存在節點出入現象, 即新節點加入集群, 老節點退出集群. 出現這些情況時, 集群中其他節點要能感知到這種變化, 然后根據這種變化做出對應的決策.

應用場景:

○ 在分布式存儲系統中, 有一個中央控制節點負責存儲的分配, 有新的存儲節點加入進來時, 需要根據集群狀態來動態分配存儲節點, 這需要實時感知集群的狀態.
○ 在分布式SOA架構中, 服務由某一集群提供, 當消費者訪問某個服務時, 需要采用某種機制發現集群中有哪些節點可以提供該服務(這也稱之為服務發現, 比如Alibaba開源的SOA框架Dubbo就采用了ZooKeeper作為服務發現的底層機制).
○ 開源的消息隊列Kafka中, 通過ZooKeeper對Consumer的上下線進行管理.

3 部署ZooKeeper集群

3.1 下載並解壓安裝包

ZooKeeper下載地址: http://hadoop.apache.org/zookeeper/releases.html.

# 下載后, 上傳至特定目錄, 這里上傳至/data/zookeeper下: 
mkdir -p /data/zookeeper && cd /data/zookeeper
# 解壓ZooKeeper安裝包: 
tar -zxf zookeeper-3.4.10.tar.gz

3.2 創建data和datalog目錄

# 進入ZooKeeper安裝目錄
cd zookeeper-3.4.10

# data為ZooKeeper數據存放目錄, datalog為ZooKeeper日志存放目錄
# 若不指定datalog, 默認與數據存放目錄一致
mkdir data datalog

# 賦予當前用戶寫權限
chmod 644 data datalog 

3.3 創建myid文件

在data目錄下創建myid文件, 文件中只包含一行內容: 該節點對應的server.id的id編號. 如server.1節點中myid文件的內容為1.

# 將編號寫入到myid文件中
echo 1 > /data/zookeeper/data/myid

# 查看寫入是否成功
cat /data/zookeeper/data/myid

3.4 修改配置文件zoo.cfg

(1) 修改過程如下:

cd /data/zookeeper/zookeeper-3.4.10/conf

# 拷貝文件, 重命名為zoo.cfg
cp zoo_sample.cfg zoo.cfg

# 修改zoo.cfg文件: 
vim zoo.cfg

# 添加如下內容: 
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/datalog
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

(2) 配置完成的zoo.cfg文件如下:

  # 基本事件單元(毫秒), 用來控制心跳和超時. 
  tickTime=2000 
  
  # 集群中有多台Server, 其中一台為Leader, 其余Server為Follower. initLimit參數指定Follower連接並同步到Leader的初始化心跳時間(即最長通信時間), 以tickTime的倍數表示, 超過該時間則連接失敗.
  initLimit=5
  
  # Leader與Follower之間發送消息時, 請求和應答的最大時間, 是tickTime的倍數. 如果Follower在設置的時間內不能與Leader建立通信, 此Follower將被丟棄. 
  syncLimit=2
  
  # 存放ZooKeeper運行時數據的目錄, 需要提前建立. 
  dataDir=/data/zookeeper/data
  
  # log目錄, 如果沒有設置該參數, 默認使用dataDir的目錄, 需要提前建立. 
  # 應當謹慎選擇日志目錄, 使用專用的日志存儲設備能很大程度提高系統的性能. 
  dataLogDir=/data/zookeeper/datalog
  
  # 監聽client連接的端口號. 
  clientPort=2181
  
  # 設置連接到ZooKeeper的客戶端的最大數量(限制並發連接的數量, 它通過IP來區分不同的客戶端). 此配置選項可以用來阻止某些類別的Dos攻擊, 將它設置為0或不設置將會取消對並發連接的限制. 
  maxClientCnxns=0
  
  # 最小的會話超時時間, 默認為 2 * tickTme 時間
  minSessionTimeout=4000
  
  # 最大的會話超時時間默認情況下為 20 倍的會話超時時間
  maxSessionTimeout=10000
  
  # 集群中各個節點的信息(server.id=ip:port1:port2)
  server.1=zoo1:2888:3888 
  server.2=zoo2:2888:3888 
  server.3=zoo3:2888:3888

(3) 關於 server.id=host:port1:port2 的說明:

id 是每個ZooKeeper節點的編號, 保存在dataDir目錄下的myid文件中;

zoo1~zoo3表示各個ZooKeeper節點的hostname或IP地址, 映射關系在系統文件 /etc/hosts 中設置;

port1指定該Server與集群中的Leader通信所使用的端口;

port2指定集群選舉Leader時所用的端口.

(4) 常見錯誤說明:

clientPort 不能與port1、port2相同, 否則集群將啟動不了.
○ 若采用偽分布式配置方式(即在一台服務器上模擬配置集群), 則各個Server的port1與port2不能相同.
○ 如果采用偽分布式配置方式, dataDir與dataLogDir也需要作不同的配置.

3.5 部署其他節點上的服務

# 拷貝ZooKeeper文件夾到其他服務器(zoo2和zoo3) --- 需要確保相應的路徑/data/zookeeper存在: 
scp -r /data/zookeeper zoo2:/data/
scp -r /data/zookeeper zoo2:/data/

# 分別在zoo2和zoo3服務器上修改ZooKeeper的myid: 
echo 2 > /data/zookeeper/zookeeper-3.4.10/data/myid
echo 3 > /data/zookeeper/zookeeper-3.4.10/data/myid

4 啟動ZooKeeper集群

4.1 關閉防火牆

ZooKeeper客戶端使用2181端口號, 為了能對外正常使用Zookeeper, 需要開放2181端口號, 或者關閉防火牆:

(1) CentOS 7之前系統的命令:

# 查看防火牆狀態: 
service iptable status

# 臨時關閉防火牆: 
service iptables stop

# 永久關閉防火牆(禁止開機啟動): 
chkconfig iptables off

(2) CentOS 7開始使用systemctl來管理服務和程序, 包括servicechkconfig:

# 查看防火牆狀態: 
systemctl status firewalld.service

# 臨時關閉防火牆: 
systemctl stop firewalld.service

# 永久關閉防火牆(禁止開機啟動): 
systemctl disable firewalld.service 

4.2 啟動ZooKeeper集群

(1) 啟動步驟:

# 依次進入三台服務器, 執行下述命令: 
cd /usr/local/zookeeper-3.4.10/bin
./zkServer.sh start

# 查看ZooKeeper運行狀態: 
./zkServer.sh status

(2) 常見錯誤: 在查看ZooKeeper的狀態時, 可能會發現控制台拋出錯誤:

[root@localhost bin]# ./zkServer.sh status 
JMX enabled by default 
Using config: /data/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg 
Error contacting service. It is probably not running 
  • 錯誤原因: 這里部署的是集群, 其他服務器尚未啟動, 當前節點在根據zoo.cfg中配置的服務列表發起選舉Leader的請求, 由於無法與集群中的其他節點進行通信, 所以拋出錯誤.

  • 錯誤解決: 在啟動第二台ZooKeeper服務后, Leader將被選出, 錯誤就會消失. 因為在ZooKeeper集群中, 如果有2n+1台服務器, 它允許n台服務掛掉而不影響服務.

4.3 ZooKeeper的常用命令

# 啟動服務: 
sh zkServer.sh start 

# 查看服務狀態: 
sh zkServer.sh status 

# 停止服務: 
sh zkServer.sh stop 

# 重啟服務: 
sh zkServer.sh restart  

版權聲明

作者: 馬瘦風

出處: 博客園 馬瘦風的博客

您的支持是對博主的極大鼓勵, 感謝您的閱讀.

本文版權歸博主所有, 歡迎轉載, 但請保留此段聲明, 並在文章頁面明顯位置給出原文鏈接, 否則博主保留追究相關人員法律責任的權利.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM