ZooKeeper系列文章:https://www.cnblogs.com/f-ck-need-u/p/7576137.html#zk
ZooKeeper有三種安裝模式:單機安裝(standalone)、偽集群模式、集群模式:
- standalone模式:只在一台機器上安裝ZooKeeper,並只啟動一個ZooKeeper實例。
- 偽集群:在一台機器上開啟多個ZooKeeper實例來模擬集群。通過加載不同配置文件,分配不同數據目錄來實現這種模式。因為在同一機器上運行,所以機器宕機,整個ZooKeeper就掛了。基本上不會布置這樣的ZooKeeper集群。
- 集群模式:在至少3台機器上安裝ZooKeeper構成集群,只要故障節點數量在一定范圍內就能保證ZooKeeper服務的可用性。
真正布置的基本上都是集群模式,standalone偶爾用來做些測試,它有單點故障,偽集群模式也有單點故障。
集群模式並非一定至少3台機器,但用2台機器比1台機器更危險,因為隨便故障一台都無法滿足"大多數"的要求,都會阻塞整個ZooKeeper服務。而2台機器的故障幾率是1台機器的2倍。所以,也建議采用奇數台機器來部署ZooKeeper。
ZooKeeper下載:https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/
我下載的是3.4.12版本。
1.安裝jdk
ZooKeeper運行在java環境下,所以需要先安裝jdk,且要求版本高於1.6。
jdk下載:http://www.oracle.com/technetwork/java/javase/downloads/index.html
以rpm包的為例。
yum localinstall -y jdk-8u131-linux-x64.rpm
rpm包的安裝路徑為/usr/java。
[root@s1 ~]# ls -l /usr/java/
total 4
lrwxrwxrwx 1 root root 16 Jun 26 22:53 default -> /usr/java/latest
drwxr-xr-x 9 root root 4096 Jun 26 22:53 jdk1.8.0_131
lrwxrwxrwx 1 root root 22 Jun 26 22:53 latest -> /usr/java/jdk1.8.0_131
通過這種軟鏈接方式,以后有新版jdk要安裝,直接改latest的鏈接對象即可。
然后再設置JAVA_HOME環境變量並導出java程序所在目錄的PATH環境變量。
echo 'JAVA_HOME=/usr/java/latest' > /etc/profile.d/jdk.sh
echo 'PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile.d/jdk.sh
chmod +x /etc/profile.d/jdk.sh
source /etc/profile.d/jdk.sh
2.StandAlone模式
standalone模式是在單機上安裝ZooKeeper。
先解壓zookeeper-3.4.12.tar.gz。
tar xf zookeeper-3.4.12.tar.gz
再把它移到/usr/local/下方便管理。
mv zookeeper-3.4.12 /usr/local/zookeeper
在ZooKeeper的bin目錄下提供了幾個Windows和Linux下的腳本:
[root@s2 zookeeper]# cd /usr/local/zookeeper
[root@s2 zookeeper]# ls bin
README.txt zkCleanup.sh zkCli.cmd zkCli.sh zkEnv.cmd zkEnv.sh zkServer.cmd zkServer.sh
- zkServer:用於啟動、停止ZooKeeper,且能查看ZooKeeper狀態。
zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
- zkEnv:設置ZooKeeper啟動、關閉時的環境變量。在其余的每個腳本中都引用了這個腳本。
- zkCleanup:清除ZooKeeper的事務日志和快照。
- zkCli:ZooKeeper的一個命令行客戶端。
設置ZooKeeper的環境變量,這不是必須的,只是為了方便操作上面的幾個腳本。
echo 'ZOOKEEPER_HOME=/usr/local/zookeeper' >/etc/profile.d/zk.sh
echo 'PATH=$ZOOKEEPER_HOME/bin:$PATH' >> /etc/profile.d/zk.sh
chmod +x /etc/profile.d/zk.sh
source /etc/profile.d/zk.sh
把windows下的腳本刪除:
rm -rf /usr/local/zookeeper/bin/{*.cmd,README.txt}
為了啟動ZooKeeper,先提供一個配置文件。默認配置文件的路徑為$ZOOKEEPER_HOME下的conf目錄。在這個目錄下,有幾個文件:
[root@s2 zookeeper]# ls conf
configuration.xsl log4j.properties zoo_sample.cfg
configuration.xsl
:無視它。log4f.properties
:是ZooKeeper的日志配置文件。zoo_sample.cfg
:是ZooKeeper的示例配置文件。
zkServer.sh默認的配置文件名為zoo.cfg
。所以,在conf目錄下創建一個zoo.cfg。寫入幾個保證ZooKeeper能正常運行的配置項:
tickTime=2000
dataDir=/usr/local/zookeeper/data1
clientPort=2181
其中:
tickTime
:ZooKeeper中很多配置項(如心跳時間、連接超時時間等)都要用到的時間單位,這里配置為2000毫秒,即2秒。dataDir
:ZooKeeper實例的數據目錄。clientPort
:ZooKeeper向外提供服務的端口。
然后用zkServer.sh來啟動ZooKeeper。
[root@s2 zk]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
也可以手動指定啟動時讀取的配置文件:
[root@s2 zk]# zkServer.sh start /usr/local/zookeeper/conf/zoo.cfg
查看ZooKeeper的運行狀態:
[root@s2 zk]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: standalone
可以看到運行模式是"standalone"。
ZooKeeper啟動后,就可以向外提供ZooKeeper服務了。這里用ZooKeeper提供的命令行客戶端去連接一下ZooKeeper做個簡單的測試。
連接ZooKeeper實例:
zkCli.sh -server localhost:2181
連接過程中會輸出一大堆信息。當連接成功后,將進入ZooKeeper的交互式模式:
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] # 在這里輸入ZooKeeper允許的命令
例如,創建一個znode:
[zk: localhost:2181(CONNECTED) 0] create /zk_test mydata1
Created /zk_test
[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper, zk_test]
[zk: localhost:2181(CONNECTED) 2] quit
3.配置偽集群模式
ZooKeeper的偽集群模式是在一個服務器上運行多個ZooKeeper實例來模擬ZooKeeper集群。偽集群模式下,每個實例的配置文件不同、數據目錄不同、端口不同。一般來說,ZooKeeper集群至少需要3個服務器節點。
這里,我配置3個實例的ZooKeeper偽集群,它們的數據目錄分別為$ZOOKEEPER_HOME
下的data1、data2和data3。因為稍后要向這些目錄中寫myid文件,所以先創建這3個目錄:
mkdir /usr/local/zookeeper/data{1,2,3}
先提供3個實例的配置文件,分別為$ZOOKEEPER_HOME/conf/{zoo1.cfg,zoo2.cfg,zoo3.cfg}
。
以下是zoo1.cfg內容,各配置項稍后解釋。
tickTime=2000
dataDir=/usr/local/zookeeper/data1
clientPort=2181
initLimit=5
syncLimit=2
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
以下是zoo2.cfg內容,各配置項稍后解釋。
tickTime=2000
dataDir=/usr/local/zookeeper/data2
clientPort=2182
initLimit=5
syncLimit=2
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
以下是zoo3.cfg內容,各配置項稍后解釋。
tickTime=2000
dataDir=/usr/local/zookeeper/data3
clientPort=2183
initLimit=5
syncLimit=2
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
上面的配置項中:
-
initLimit
:當非leader節點(即follower和observer)啟動時,需要先從leader那里復制數據,以保證所有ZooKeeper節點數據都是同步的。這個選項設置非leader節點從啟動到完成同步的超時時長,它以tickTime為時間單位,所以上面的超時時長為5*2=10
秒。一般來說,ZooKeeper保存的都是協調數據,數據量並不大,所以多數時候可以忽略這個參數,如果待同步數據真的很大,可以考慮增加這個超時時間。
-
syncLimit
:follower和leader之間數據延遲的最大時間長度。例如,有個節點的更新操作緩慢,它的數據已經嚴重落后於leader,ZooKeeper就會將它從ZooKeeper集群中踢出去。ZooKeeper使用時間來度量follower和leader之間數據的延遲,這個選項的值依賴於tickTime,例如tickTime=2000,syncLimit=2
表示follower比leader延遲了4秒。 -
server.X=[hostname]:port_A:port_B
:該選項用來指定ZooKeeper集群中的服務器節點。其中:- X:整數。是ZooKeeper中服務器的一個簡單標識。這個數值需要和dataDir下的myid文件內容一致。在啟動ZooKeeper集群中的每個實例時,需要讀取數據目錄中的myid文件,並將該文件中的數值和配置文件中的server.X做匹配,匹配到哪個就表示是哪個ZooKeeper服務器節點。
- hostname:ZooKeeper服務器節點的地址。
- port_A:這是第一個端口,用於Follower和Leader之間的數據同步和其它通信。
- port_B:這是第二個端口,用於Leader選舉過程中投票通信。
所以,分別在每個實例的dataDir下創建對應的myid文件。
echo 1 >/usr/local/zookeeper/data1/myid
echo 2 >/usr/local/zookeeper/data2/myid
echo 3 >/usr/local/zookeeper/data3/myid
然后啟動這3個ZooKeeper實例。
zkServer.sh start /usr/local/zookeeper/conf/zoo1.cfg
zkServer.sh start /usr/local/zookeeper/conf/zoo2.cfg
zkServer.sh start /usr/local/zookeeper/conf/zoo3.cfg
查看當前java進程列表:
[root@s1 zk]# jps -l
5473 org.apache.zookeeper.server.quorum.QuorumPeerMain
5395 org.apache.zookeeper.server.quorum.QuorumPeerMain
5427 org.apache.zookeeper.server.quorum.QuorumPeerMain
5524 sun.tools.jps.Jps
查看這3個實例之間的關系:zoo2.cfg被選為leader,其它是follower。
[root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo3.cfg
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/conf/zoo3.cfg
Mode: follower
[root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo1.cfg
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/conf/zoo1.cfg
Mode: follower
[root@s1 zk]# zkServer.sh status /usr/local/zookeeper/conf/zoo2.cfg
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/conf/zoo2.cfg
Mode: leader
可以用ZooKeeper提供的命令行客戶端工具來測試,寫入其中一個實例的數據,其它實例也能收到。
[root@s1 zk]# zkCli.sh -server localhost:2181 create /my_znode hello
......省略.........
WatchedEvent state:SyncConnected type:None path:null
Created /my_znode
[root@s1 zk]# zkCli.sh -server localhost:2182 ls /
......省略........
WatchedEvent state:SyncConnected type:None path:null
[my_znode, zookeeper]
4.配置ZooKeeper集群
以3節點的集群為例:192.168.100.21、192.168.100.22、192.168.100.23。因為前面配置單機ZooKeeper和偽集群ZooKeeper已經解釋過所有步驟和配置項的意義,所以這里就直接給步驟。
假設已經在3個節點上都安裝好了jdk(這是前提),並下載好了ZooKeeper。
先解壓zookeeper-3.4.12.tar.gz。
# 3個節點都執行
tar xf zookeeper-3.4.12.tar.gz
mv zookeeper-3.4.12 /usr/local/zookeeper
添加ZooKeeper環境變量,非必須過程,但建議。
# 在3節點上都執行
echo 'ZOOKEEPER_HOME=/usr/local/zookeeper' >/etc/profile.d/zk.sh
echo 'PATH=$ZOOKEEPER_HOME/bin:$PATH' >> /etc/profile.d/zk.sh
chmod +x /etc/profile.d/zk.sh
source /etc/profile.d/zk.sh
提供配置文件。以下是3個節點上的配置文件:
[root@s1 zk]# cat /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000
dataDir=/usr/local/zookeeper/data
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.100.21:2888:3888
server.2=192.168.100.22:2888:3888
server.3=192.168.100.23:2888:3888
在三個節點上都創建好數據目錄,並寫入myid文件。
# 3個節點上都執行:
mkdir /usr/local/zookeeper/data
# 192.168.100.21上執行
echo 1 >/usr/local/zookeeper/data/myid
# 192.168.100.22上執行
echo 2 >/usr/local/zookeeper/data/myid
# 192.168.100.23上執行
echo 3 >/usr/local/zookeeper/data/myid
啟動這3個ZooKeeper實例。
# 3個節點都執行:
zkServer.sh start
然后在3個節點上都驗證一下是否正確啟動ZooKeeper。
# 節點1上執行:
[root@s1 zk]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
# 節點2上執行:
[root@s2 zk]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
# 節點3上執行:
[root@s3 zk]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader
如果某個服務器實例出現了錯誤,請zkServer.sh stop
關閉ZooKeeper實例,然后jps
命令查看下是否還有ZooKeeper實例在運行,如果有,kill掉。然后再啟動ZooKeeper。另外,建議在第一次啟動ZooKeeper之前,先將dataDir/version-2目錄刪除(如果已存在,因為可能是以前的實例因為各種原因而留下來的)。
最后測試下,某節點上創建一個znode,其它節點是否也同步了該節點。
# 在192.168.100.21上創建一個znode:
[root@s2 zk]# zkCli.sh -server 192.168.100.21:2181 create /test_znode "hello world"
Connecting to 192.168.100.21:2181
.........省略..........
Created /test_znode
# 在192.168.100.22上獲取這個znode
[root@s2 zk]# zkCli.sh -server 192.168.100.22:2181 get /test_znode
Connecting to 192.168.100.22:2181
.........省略..........
hello world
cZxid = 0x100000002
ctime = Wed Jun 27 08:14:38 CST 2018
mZxid = 0x100000002
mtime = Wed Jun 27 08:14:38 CST 2018
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0
# 在192.168.100.23上獲取這個znode
[root@s2 zk]# zkCli.sh -server 192.168.100.23:2181 ls /
Connecting to 192.168.100.23:2181
.........省略..........
[zookeeper, test_znode]