Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。
ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。
每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住。
在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求
[root@bigdata01 ~]# java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
[root@bigdata01 ~]# ll -d /opt/module/*zoo*
drwxr-xr-x 6 root root 133 Feb 4 22:30 /opt/module/apache-zookeeper-3.6.2-bin
lrwxrwxrwx 1 root root 27 Feb 4 22:30 /opt/module/zookeeper -> apache-zookeeper-3.6.2-bin/
[root@bigdata01 ~]#
[root@bigdata01 ~]# cd /opt/module/zookeeper/conf/
[root@bigdata01 conf]# grep -Ev '^$|^#' zoo_sample.cfg > zoo.cfg
[root@bigdata01 conf]# vi zoo.cfg
[root@bigdata01 conf]# cat zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/module/zookeeper/zkData
clientPort=2181
[root@bigdata01 conf]#
[root@bigdata01 conf]# cat zoo_sample.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
## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true
[root@bigdata01 conf]#
参数 | 说明 |
---|---|
tickTime =2000 | 服务器与客户端心跳时间,单位毫秒 |
initLimit =10 | Follower与Leader之间初始连接时能容忍的最多心跳数(tickTime的数量) |
syncLimit =5 | 集群中Leader与Follower之间的最大响应时间单位(tickTime的数量) |
dataDir | 数据文件目录+数据持久化路径 |
clientPort =2181 | 客户端连接端口 |
[root@bigdata01 bin]# pwd
/opt/module/zookeeper/bin
[root@bigdata01 bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@bigdata01 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
[root@bigdata01 bin]#
[root@bigdata01 bin]# ./zkCli.sh
[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 2] quit
[root@bigdata01 bin]#
[root@bigdata01 bin]# ./zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
[root@bigdata01 bin]#
持久(Persistent):客户端和服务器端断开连接后,创建的节点不删除
短暂(Ephemeral):客户端和服务器端断开连接后,创建的节点自己删除
创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护;
注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。
- | - |
---|---|
czxid | 创建节点的事务zxid。每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID;事务ID是ZooKeeper中所有修改总的次序,每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。 |
ctime | znode被创建的毫秒数(从1970年开始) |
mzxid | znode最后更新的事务zxid |
mtime | znode最后修改的毫秒数(从1970年开始) |
pZxid | znode最后更新的子节点zxid |
cversion | znode子节点变化号,znode子节点修改次数 |
dataversion | znode数据变化号 |
aclVersion | znode访问控制列表的变化号 |
ephemeralOwner | 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。 |
dataLength | znode的数据长度 |
numChildren | znode子节点数量 |
get -w path
ls -w path
scheme:id:perm
策略 | 说明 |
---|---|
world | 默认方式,相当于全部都能访问 |
auth | 代表已经认证通过的用户(cli添加授权addauth digest user:pwd ) |
digest | 用 username:password 字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是通过明文发送username:password 来进行的,当用在ACL时,表达式为 username:BASE64(SHA-1(username:password)) |
ip | 使用客户端的主机IP作为ACL ID,这个ACL表达式的格式为ip/mask |
授权对象ID是指,权限赋予的用户或者一个实体,例如:IP 地址或者机器。
权限模式 | 授权对象 |
---|---|
IP | 通常是一个IP地址或是IP段,例如 192.168.1.92 或 192.168.0.1/24 |
Digest | 自定义,通常是 username:BASE64(SHA-1(username:password)) |
World | 只有一个ID:anyone |
Super | 与Digest模式一致 |
权限 | 说明 |
---|---|
CREATE | c 可以创建子节点 |
DELETE | d 可以删除子节点(仅下一级节点) |
READ | r 可以读取节点数据及显示子节点列表 |
WRITE | w 可以设置节点数据 |
ADMIN | a 可以设置节点访问控制列表权限 |
[zk: localhost:2181(CONNECTED) 7] create /acl "test-acl"
Created /acl
[zk: localhost:2181(CONNECTED) 10] getAcl /acl
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 11] setAcl /acl world:anyone:r
[zk: localhost:2181(CONNECTED) 12] getAcl /acl
'world,'anyone
: r
[zk: localhost:2181(CONNECTED) 13]
[zk: localhost:2181(CONNECTED) 14] create /test test
Created /test
[zk: localhost:2181(CONNECTED) 15] setAcl /test ip:127.0.0.1:r
[zk: localhost:2181(CONNECTED) 16] getAcl /test
'ip,'127.0.0.1
: r
[zk: localhost:2181(CONNECTED) 17]
[zk: localhost:2181(CONNECTED) 22] create /auth
Created /auth
[zk: localhost:2181(CONNECTED) 23] addauth digest rayslee:abcd1234
[zk: localhost:2181(CONNECTED) 24] setAcl /auth auth:rayslee:cdwra
[zk: localhost:2181(CONNECTED) 0] getAcl /auth
Authentication is not valid : /auth
[zk: localhost:2181(CONNECTED) 1] addauth digest rayslee:abcd1234
[zk: localhost:2181(CONNECTED) 2] getAcl /auth
'digest,'rayslee:9cN/Mfg8f75sAEv10v3hiIsEzbA=
: cdrwa
[zk: localhost:2181(CONNECTED) 3]
[omm@bigdata01 module]$ cat xsync
#!/bin/bash
hosts="bigdata02 bigdata03"
stand=`pwd`
p_dir=`cd .. && pwd`
cd $stand
for host in $hosts
do
rsync -avz --delete $stand $host:$p_dir
done
[omm@bigdata01 module]$ xsync
...
sent 15,559,042 bytes received 33,858 bytes 6,237,160.00 bytes/sec
total size is 1,319,008,659 speedup is 84.59
[omm@bigdata01 module]$
myid
[omm@bigdata01 zkData]$ pwd
/opt/module/zookeeper/zkData
[omm@bigdata01 zkData]$ echo 1 > myid
[omm@bigdata01 zkData]$
[omm@bigdata02 zkData]$ echo 2 > myid
[omm@bigdata02 zkData]$
[omm@bigdata03 zkData]$ echo 3 > myid
[omm@bigdata03 zkData]$
2888 是这个服务器与集群中的Leader服务器交换信息的端口;
3888 是用来执行选举时服务器相互通信的端口。
[omm@bigdata01 conf]$ pwd
/opt/module/zookeeper/conf
[omm@bigdata01 conf]$ cat << EOF >> zoo.cfg
> server.1=bigdata01:2888:3888
> server.2=bigdata02:2888:3888
> server.3=bigdata03:2888:3888
> EOF
[omm@bigdata01 conf]$ xsync
[omm@bigdata01 bin]$ ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[omm@bigdata01 bin]$ ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[omm@bigdata01 bin]$
命令基本语法 | 功能描述 |
---|---|
help | 显示所有操作命令 |
ls path | 使用 ls 命令来查看当前znode中所包含的内容 |
ls [-s] path | 查看当前节点数据并能看到更新次数等数据 |
ls [-w] path | 监听路径变化 |
create | 普通创建,-s 含有序列,-e 临时(重启或者超时消失) |
get path | 获得节点的值 |
get [-w] path | 监听节点值的变化 |
set | 设置节点的具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
deleteall | 递归删除节点 |
[root@bigdata03 bin]# pwd
/opt/module/zookeeper/bin
[root@bigdata03 bin]# ./zkCli.sh
[zk: localhost:2181(CONNECTED) 1] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
version
Command not found: Command not found help
[zk: localhost:2181(CONNECTED) 2]
[zk: localhost:2181(CONNECTED) 7] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 8] ls -s /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 9]
[zk: localhost:2181(CONNECTED) 10] create /simwor "beginner"
Created /simwor
[zk: localhost:2181(CONNECTED) 11] create /simwor/bigdata "zookeeper"
Created /simwor/bigdata
[zk: localhost:2181(CONNECTED) 12] create -e /simwor/frontend "javascript"
Created /simwor/frontend
[zk: localhost:2181(CONNECTED) 13] quit
[root@bigdata03 bin]# ./zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /simwor
[bigdata]
[zk: localhost:2181(CONNECTED) 1]
[zk: localhost:2181(CONNECTED) 1] create -s /simwor/sequential "001"
Created /simwor/sequential0000000002
[zk: localhost:2181(CONNECTED) 2] create -s /simwor/sequential "002"
Created /simwor/sequential0000000003
[zk: localhost:2181(CONNECTED) 3] create -s /simwor/sequential "003"
Created /simwor/sequential0000000004
[zk: localhost:2181(CONNECTED) 4] ls /simwor
[bigdata, sequential0000000002, sequential0000000003, sequential0000000004]
[zk: localhost:2181(CONNECTED) 5]
[zk: localhost:2181(CONNECTED) 5] create -e -s /simwor/temp-sequential "001"
Created /simwor/temp-sequential0000000005
[zk: localhost:2181(CONNECTED) 6] create -e -s /simwor/temp-sequential "002"
Created /simwor/temp-sequential0000000006
[zk: localhost:2181(CONNECTED) 7] create -e -s /simwor/temp-sequential "003"
Created /simwor/temp-sequential0000000007
[zk: localhost:2181(CONNECTED) 8] quit
[root@bigdata03 bin]# ./zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /simwor
[bigdata, sequential0000000002, sequential0000000003, sequential0000000004]
[zk: localhost:2181(CONNECTED) 1]
[zk: localhost:2181(CONNECTED) 1] get /simwor
beginner
[zk: localhost:2181(CONNECTED) 2] set /simwor "master"
[zk: localhost:2181(CONNECTED) 3] get /simwor
master
[zk: localhost:2181(CONNECTED) 4] get -s /simwor
master
cZxid = 0x200000017
ctime = Sat Feb 06 20:55:36 CST 2021
mZxid = 0x200000024
mtime = Sat Feb 06 21:01:15 CST 2021
pZxid = 0x200000022
cversion = 12
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 4
[zk: localhost:2181(CONNECTED) 5]
[zk: localhost:2181(CONNECTED) 16] set /simwor "beginner"
[zk: localhost:2181(CONNECTED) 17]
[zk: localhost:2181(CONNECTED) 7] get -w /simwor
master
[zk: localhost:2181(CONNECTED) 8]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/simwor
[zk: localhost:2181(CONNECTED) 8]
[zk: localhost:2181(CONNECTED) 8] ls -w /simwor
[bigdata, sequential0000000002, sequential0000000003, sequential0000000004]
[zk: localhost:2181(CONNECTED) 9]
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/simwor
[zk: localhost:2181(CONNECTED) 9]
[zk: localhost:2181(CONNECTED) 17] create /simwor/change "hallo"
Created /simwor/change
[zk: localhost:2181(CONNECTED) 18]
[zk: localhost:2181(CONNECTED) 9] ls /simwor
[bigdata, change, sequential0000000002, sequential0000000003, sequential0000000004]
[zk: localhost:2181(CONNECTED) 10] delete /simwor/bigdata
[zk: localhost:2181(CONNECTED) 11] delete /simwor
Node not empty: /simwor
[zk: localhost:2181(CONNECTED) 12] deleteall /simwor
[zk: localhost:2181(CONNECTED) 13]
[zk: localhost:2181(CONNECTED) 15] stat /zookeeper
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
[zk: localhost:2181(CONNECTED) 16]
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.simwor.zookeepergroupId>
<artifactId>ZookeeperDemoartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.1version>
parent>
<properties>
<maven.compiler.source>15maven.compiler.source>
<maven.compiler.target>15maven.compiler.target>
<spring-cloud.version>2020.0.0spring-cloud.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
package com.simwor.zookeeper;
import org.apache.zookeeper.*;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import java.io.IOException;
// Watcher 即 ZooKeeper 发生变化后应该如何处理(process方法)
public class ZooKeeperTest implements Watcher {
private static ZooKeeper zk;
public static void main(String[] args) throws IOException, InterruptedException {
// ZooKeeper 实例,包含集群地址和 Watcher 实例。
zk = new ZooKeeper("192.168.1.101:2181,192.168.1.102:2181,192.168.1.103:2181", 5000, new ZooKeeperTest());
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
// 连接成功后调用 doSomething 方法
if (event.getState() == KeeperState.SyncConnected) {
doSomething();
}
}
private void doSomething() {
try {
// 创建
String path = zk.create("/test", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("return path:" + path);
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}