ZooKeeper集群搭建、命令操作


Zookeeper搭建方式可以分为单机模式、集群模式、伪集群模式。在集群模式下,节点的个数建议为奇数个,且至少为3个节点。因为Zookeeper的leader选取至少要有半数以上的节点。

Zookeeper的搭建方式

  • 单机模式: Zookeeper只运行在一台服务器上,适合测试环境
  • 伪集群模式: 在一台物理机上运行多个Zookeeper实例
  • 集群模式: Zookeeper运行于一个集群上,适合生产环境

单机模式搭建

要搭建Zookeeper环境,首先要先安装JAVA开发环境。

下载ZooKeeper:

https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/

解压:

tar xzf zookeeper-3.4.12.tar.gz

在conf目录下创建一个配置文件zoo.cfg:

cd zookeeper-3.4.12
[heql@ubuntu zookeeper-3.4.12]$ cp conf/zoo_sample.cfg conf/zoo.cfg
配置文件

配置文件zoo.cfg的内容

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
配置项 含义
tickTime Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,每隔tickTime时间就会发送一个心跳
initLimit 允许follower连接并同步到Leader的初始化连接时间,以tickTime为单位。当初始化连接时间超过该值,则表示连接失败
syncLimit 表示Leader与follower之间发送消息时,请求和应答时间长度。如果follower在设置时间内不能与leader通信,那么此follower将会被丢弃。
dataDir 存储内存中数据库快照的位置
clientPort Zookeeper的端口号
maxClientCnxns 限制连接到Zookeeper的客户端数量

运行:

[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh start

查看运行状态:

[heql@ubuntu zookeeper-3.4.12]$ jps
7309 QuorumPeerMain
7887 Jps

伪集群模式搭建

在一台物理机上运行多个Zookeeper实例,这些Zookeeper实例可以组成伪集群模式。在集群为分布式模式下,必须保证每个zoo.conf的各个端口号不能冲突,除了clientPort不同之外,dataDir也不同。另外,还要在dataDir所对应的目录中创建myid文件来指定对应的Zookeeper服务器实例。

在本机上运行3个Zookeeper实例,它们对应的配置文件分别为zoo_2181.cfgzoo_2182.cfgzoo_2183.cfg

如下为zoo_2181.cfg配置文件的内容:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/opt/zookeeper/data_2181
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

server.0=127.0.0.1:2287:3387
server.1=127.0.0.1:2288:3388
server.2=127.0.0.1:2289:3389

server.A=B:C:D

  • A:其中A是一个数字,表示这个是服务器的编号,对应不同服务器的myid文件内容
  • B:是这个服务器的 ip 地址
  • C:Leader选举的端口
  • D:Zookeeper服务器之间的通信端口

zoo_2182.cfgzoo_2183.cfgzoo_2181.cfg配置文件与上面类似,只是clientPortdataDir不同。

zoo_2182.cfgclientPortdataDir为:

dataDir=/opt/zookeeper/data_2182
clientPort=2182

zoo_2183.cfgclientPortdataDir为:

dataDir=/opt/zookeeper/data_2183
clientPort=2183

/opt/zookeeper/目录下创建data_2181data_2182data_2183。在data_2181目录创建一个data_2181data_2182data_2183分别创建一个myid文件,内容分别为0、1、2。

启动Zookeeper服务:

[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh start conf/zoo_2181.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2181.cfg
Starting zookeeper ... STARTED
[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh start conf/zoo_2182.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2182.cfg
Starting zookeeper ... STARTED
[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh start conf/zoo_2183.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2183.cfg
Starting zookeeper ... STARTED

查看启动结果:

[heql@ubuntu zookeeper-3.4.12]$ jps
3232 QuorumPeerMain
3331 Jps
3300 QuorumPeerMain
3259 QuorumPeerMain

Zookeeper服务的运行状态:

[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh status conf/zoo_2181.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2181.cfg
Mode: follower
[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh status conf/zoo_2182.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2182.cfg
Mode: leader
[heql@ubuntu zookeeper-3.4.12]$ bin/zkServer.sh status conf/zoo_2183.cfg 
ZooKeeper JMX enabled by default
Using config: conf/zoo_2183.cfg
Mode: follower

Zookeeper命令操作

启动Zookeeper服务之后,可以使用Zookeeper自带的客户端zkCli.sh,连接到Zookeeper服务,进行相应的操作。

[heql@ubuntu zookeeper-3.4.12]$ bin/zkCli.sh -server 127.0.0.1:2181

基本操作

连上服务器后,可以执行help命令,查看Zookeeper支持的命令操作:

[zk: 127.0.0.1:2181(CONNECTED) 1] help
ZooKeeper -server host:port cmd args
    stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history 
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit 
    getAcl path
    close 
    connect host:port
  1. 使用ls命令查看当前Zookeeper节点中所包含的内容:

    [zk: 127.0.0.1:2181(CONNECTED) 2] ls /
    [zookeeper]
    
  2. 创建一个新的Znode节点app,数据为test

    [zk: 127.0.0.1:2181(CONNECTED) 3] create /app test
    Created /app
    [zk: 127.0.0.1:2181(CONNECTED) 4] ls /
    [app, zookeeper]
    
  3. 使用get命令,查看节点的信息:

    [zk: 127.0.0.1:2181(CONNECTED) 5] get /app
    test
    cZxid = 0x100000002
    ctime = Wed Jun 20 20:15:00 CST 2018
    mZxid = 0x100000002
    mtime = Wed Jun 20 20:15:00 CST 2018
    pZxid = 0x100000002
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 4
    numChildren = 0
    
  4. set命令来可以更新节点的数据:

    [zk: 127.0.0.1:2181(CONNECTED) 6] set /app update_test
    cZxid = 0x100000002
    ctime = Wed Jun 20 20:15:00 CST 2018
    mZxid = 0x100000003
    mtime = Wed Jun 20 20:17:53 CST 2018
    pZxid = 0x100000002
    cversion = 0
    dataVersion = 1
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 11
    numChildren = 0
    [zk: 127.0.0.1:2181(CONNECTED) 7] get /app
    update_test
    cZxid = 0x100000002
    ctime = Wed Jun 20 20:15:00 CST 2018
    mZxid = 0x100000003
    mtime = Wed Jun 20 20:17:53 CST 2018
    pZxid = 0x100000002
    cversion = 0
    dataVersion = 1
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 11
    numChildren = 0
    [zk: 127.0.0.1:2181(CONNECTED) 8] 
    
  5. 删除节点:

    [zk: 127.0.0.1:2181(CONNECTED) 8] delete /app
    [zk: 127.0.0.1:2181(CONNECTED) 9] ls /
    [zookeeper]
    
ACL权限控制

Zookeeper的ACL,分为三个维度:scheme、id、permission,通常表示为:scheme:id:permission,schema代表授权策略,id代表用户,permission代表权限。

scheme

scheme即采取的授权策略,每种授权策略对应不同的权限校验方式。下面是Zookeeper常用的几种scheme:

digest

语法:digest:username:BASE64(SHA1(password)):cdrwa

  • digest:是授权方式
  • username:BASE64(SHA1(password)):是id部分
  • cdrwa:权限部份

用户名+密码授权访问方式,是常用的一种授权策略。id部份是用户名和密码做sha1加密再做BASE64加密后的组合,比如设置一个节点的用户名为heql,密码为123456,则表示方式为:heql:BASE64(SHA1(123456)) ⇒ heql:W+qVWaUSzd7VWFNOpAVhryXr8xI=

密码加密需要用到Zookeeper的一个工具类来生成,如下所示:

[heql@ubuntu zookeeper-3.4.12]$ java -Djava.ext.dirs=./lib -cp zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider heql:123456
heql:123456->heql:W+qVWaUSzd7VWFNOpAVhryXr8xI=

下面是演示创建节点,并添加授权信息操作节点的示例:

创建节点:

[zk: 127.0.0.1:2181(CONNECTED) 6] create /node data
Created /node

设置权限:

[zk: 127.0.0.1:2181(CONNECTED) 7] setAcl /node digest:heql:W+qVWaUSzd7VWFNOpAVhryXr8xI=:cdrwa
cZxid = 0x100000008
ctime = Wed Jun 20 20:34:02 CST 2018
mZxid = 0x100000008
mtime = Wed Jun 20 20:34:02 CST 2018
pZxid = 0x100000008
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

获取节点设置的权限:

[zk: 127.0.0.1:2181(CONNECTED) 8] getAcl /node
'digest,'heql:W+qVWaUSzd7VWFNOpAVhryXr8xI=
: cdrwa

没有授权,创建节点失败:

[zk: 127.0.0.1:2181(CONNECTED) 9] create /node/node_01 data
Authentication is not valid : /node/node_01

添加授权信息,就可以正常操作:

[zk: 127.0.0.1:2181(CONNECTED) 10] addauth digest heql:123456
[zk: 127.0.0.1:2181(CONNECTED) 11] create /node/node_01 data 
Created /node/node_01
[zk: 127.0.0.1:2181(CONNECTED) 12] ls /node
[node_01]
ip

基于客户端IP地址校验,限制只允许指定的客户端能操作znode。

比如,设置某个节点只允许IP为192.168.1.100的客户端能读写该写节点的数据:ip:192.168.1.100:rw

setAcl /node_08 ip:192.168.1.100:rw
world

语法:world:anyone:cdrwa

创建节点默认的scheme,所有人都可以访问。

zk: 127.0.0.1:2181(CONNECTED) 24] create /node_02 data
Created /node_02
[zk: 127.0.0.1:2181(CONNECTED) 25] getAcl /node_02     
'world,'anyone
: cdrwa
id

id是验证模式,不同的scheme,id的值也不一样。scheme为digest时,id的值为:username:BASE64(SHA1(password)),scheme为ip时,id的值为客户端的ip地址。scheme为world时,id的值为anyone。

permission

digest:username:BASE64(SHA1(password)):cdrwa中的cdrwa即是permission

  • CREATE(r):创建子节点的权限
  • DELETE(d):删除节点的权限
  • READ(r):读取节点数据的权限
  • WRITE(w):修改节点数据的权限
  • ADMIN(a):设置子节点权限的权限