1.why zookeeper
现在各个服务大部分都是集群。多个节点一起工作。就是传说中的分布式。
多个节点工作肯定不会个一个节点工作一模一样。需要来进行数据的同步等。高并发,就需要上锁。这里是分布式锁。不是单台机器的锁。
zookeeper 就是为了解决这些问题的。
zookeeper 是分布式协调服务。
登录官网看咋说的
准备用谷歌在线翻译。发现用不了了。。呵呵
使用微信翻译
可以维护配置信息,比如kafka的配置信息?
命名?这个不懂。
分布式同步。就是多个节点数据同步。
提供服务。
zookeeper就是把我们业务需要做的公共的东西做了。咱只需要关系咱自己的业务。出现bug。一般是咱自己导致的。不是zookeeper。
2.zookeeper应用场景
学习kafka的时候,前提就是zookeeper.
2.1、分布式协调组件
协调分布式中系统的状态。
2.2、分布式锁
比如俩个主机A和B 提供一样的服务,同一个数据D,有人请求肯定在其中一个主机上,如果修改了主机A的数据D。 那么B上的D也应该被修改。这就是zookeeper做的事,使用分布式锁,保证了数据的一致性。强一致性 或 最终一致性。
2.3、无状态化的实现
现在流行无状态化,就是服务器只负责处理数据,而不保存数据,每个节点都一样。这样扩缩容就很简单。数据肯定 是去其他地方保存了。那么就是zookeeper.但是zookeeper不能当做数据库一样来保存数据。
3.安装zookeeper
就是到官方下载包。然后解压就完事了。一般安装在 /usr/local
zookeeper的目录
- bin 就是一些可以执行的命令。比如启动/停止zk. 客户端连接zk等。
- conf 配置文件的地方,每个软件一般都叫这个玩意。一些配置数据,启动数据就在这里
zk的配置文件一般是zoo.cfg
zoo_sample.cfg是示例
- logs
默认保存数据、日志的路径
4.使用zookeeper.单节点
4.1 启动前需要先编辑配置文件
zoo.cfg配置如下
tickTime=2000 # zk最小时间单位。2s
dataDir=/var/lib/zookeeper # zk保存数据的路径,如果没有logdatadir,log也在这个路径
clientPort=2181 # 客户端连接zk的端口
4.2 启动zk
在 bin目录下
./zkServer.sh start
还可以指定配置文件,默认就是config下的zoo.cfg
PS:使用zk,先要安装好jdk. 毕竟是apache的。
4.3 查看zk状态
./zkServer.sh status
Mode: standalone
4.4 停止服务器
./zkServer.sh stop
5.使用zkCli 客户端 来连接zk服务端,来学习一些基本命令
5.1 使用zkCli连接命令
./zkCli.sh
5.2 输入help就会有命令提示帮助,告诉我们有哪些命令可以执行
[zk: localhost:2181(CONNECTED) 0] 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|-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|-N|-B val path
stat [-w] path
sync path
version
whoami
5.3、版本、获取节点信息
[zk: localhost:2181(CONNECTED) 1] version
ZooKeeper CLI version: 3.8.0-5a02a05eddb59aee6ac762f7ea82e92a68eb9c0f, built on 2022-02-25 08:49 UTC
[zk: localhost:2181(CONNECTED) 2] whoami
Auth scheme: User
ip: 0:0:0:0:0:0:0:1
[zk: localhost:2181(CONNECTED) 4] get /
[zk: localhost:2181(CONNECTED) 5]
- zk保存数据的格式
zk保存数据的格式 是 类似目录的。 树结构。
基于节点来保存的。叫znode.
根路径 /
根路径下test节点 /test
test 节点下还可以有 /test/test_sub
5.4、创建节点
zk有多种类型的节点.对应不同的命令
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
5.4.1 持久节点
创建出来的节点。会话结束后还存在
[zk: localhost:2181(CONNECTED) 5] create /test1 ll
Created /test1
5.4.2 持久序号节点
根据先后顺序。在节点之后带上一个数值,数值递增。 应用于分布式场景。 来区分不同的并发,时间先后。
[zk: localhost:2181(CONNECTED) 6] create -s /test2 ll2
Created /test20000000016
[zk: localhost:2181(CONNECTED) 7] create -s /test2 ll22
Created /test20000000017
[zk: localhost:2181(CONNECTED) 9] create /test1 ll2
Node already exists: /test1
名称后面自动加一个数值。
序号节点创建同名的不会报错。
创建同名的非序号节点,就会说已经存在
5.4.3 临时节点
会话结束,该节点就没了
[zk: localhost:2181(CONNECTED) 8] create -e /test3 ll3
Created /test3
5.4.4 临时序号节点
用于临时的分布式锁场景。
[zk: localhost:2181(CONNECTED) 10] create -s -e /test4 ll4
Created /test40000000019
[zk: localhost:2181(CONNECTED) 11] create -s -e /test4 ll42
Created /test40000000020
5.5 查看节点信息
5.5.1 首先查看有哪些节点
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 17] ls /
[admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, test1, test20000000016, test20000000017, test3, test40000000019, test40000000020, zookeeper]
默认只能查看当前路径下的节点。
- -R : 一般是递归的意思,可以查看子路径下的节点信息
[zk: localhost:2181(CONNECTED) 18] ls -R /
/
/admin
/brokers
/cluster
/config
/consumers
/controller_epoch
/feature
/isr_change_notification
/latest_producer_id_block
/log_dir_event_notification
/test1
/test20000000016
/test20000000017
/test3
/test40000000019
/test40000000020
/zookeeper
/admin/delete_topics
/brokers/ids
/brokers/seqid
/brokers/topics
/brokers/topics/test
/brokers/topics/test/partitions
/brokers/topics/test/partitions/0
/brokers/topics/test/partitions/0/state
/cluster/id
/config/brokers
/config/changes
/config/clients
/config/ips
/config/topics
/config/users
/config/topics/test
/consumers/console-consumer-20678
/consumers/console-consumer-20678/offsets
/consumers/console-consumer-20678/offsets/test
/consumers/console-consumer-20678/offsets/test/0
/zookeeper/config
/zookeeper/quota
5.5.2 查看具体某个节点的信息
get [-s] [-w] path
- 查看当前节点保存的数据
[zk: localhost:2181(CONNECTED) 19] get /test1
ll
- 查看当前节点的元数据
[zk: localhost:2181(CONNECTED) 20] get -s /test1
ll # 数据
cZxid = 0xa1 # 创建事务ID
ctime = Sun Jan 01 20:36:36 HKT 2023 # 创建时间
mZxid = 0xa1 # 修改事务ID
mtime = Sun Jan 01 20:36:36 HKT 2023 # 修改时间
pZxid = 0xa1 # 添加/删除子节点的事务ID
cversion = 0 #
dataVersion = 0 # 节点数据版本,每修改一次,就递增1
aclVersion = 0 # 此节点的权限版本
ephemeralOwner = 0x0 # 如果当前节点是临时节点,是当前节点所有者的session id。如果节点不是临时节点,则该值为零
dataLength = 2 # 节点内数据的长度
numChildren = 0 # 节点的子节点个数
table键会有提示
[zk: localhost:2181(CONNECTED) 22] get -s /test2000000001
test20000000016 test20000000017
[zk: localhost:2181(CONNECTED) 22] get -s /test20000000016
ll2
cZxid = 0xa2
ctime = Sun Jan 01 20:45:13 HKT 2023
mZxid = 0xa2
mtime = Sun Jan 01 20:45:13 HKT 2023
pZxid = 0xa2
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 23] get -s /test3
ll3
cZxid = 0xa4
ctime = Sun Jan 01 20:47:47 HKT 2023
mZxid = 0xa4
mtime = Sun Jan 01 20:47:47 HKT 2023
pZxid = 0xa4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x10002ee9e300000
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 24] get -s /test400000000
test40000000019 test40000000020
[zk: localhost:2181(CONNECTED) 24] get -s /test40000000019
ll4
cZxid = 0xa6
ctime = Sun Jan 01 20:50:04 HKT 2023
mZxid = 0xa6
mtime = Sun Jan 01 20:50:04 HKT 2023
pZxid = 0xa6
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x10002ee9e300000
dataLength = 3
numChildren = 0
5.6 权限设置
5.6.1 注册当前会话的账号和密码
addauth scheme auth
- 节点的权限
c: create,创建
w: write,更新
d: delete,删除
a: admin,管理者,进行acl权限设置
r: read,读
[zk: localhost:2181(CONNECTED) 27] addauth digest lzl:123
[zk: localhost:2181(CONNECTED) 28]
lzl 是用户 123 是密码
[zk: localhost:2181(CONNECTED) 28]
[zk: localhost:2181(CONNECTED) 28] create /test5 ll5 auth:lzl:123:cdw
Created /test5
[zk: localhost:2181(CONNECTED) 29] get /test5
Insufficient permission : /test5
[zk: localhost:2181(CONNECTED) 30] getAcl -s /test5
Insufficient permission : /test5
[zk: localhost:2181(CONNECTED) 31] whoami
Auth scheme: User
digest: lzl
ip: 0:0:0:0:0:0:0:1
[zk: localhost:2181(CONNECTED) 35] create /test6 ll6 auth:lzl:123:cdwra
Created /test6
[zk: localhost:2181(CONNECTED) 36] get /test6
ll6
[zk: localhost:2181(CONNECTED) 38] getAcl /test6
'digest,'lzl:ctz2pGX7T978GzU15rvOzb8mJeM=
: cdrwa
5.7 删除节点
delete [-v version] path
- 删除持久节点
[zk: localhost:2181(CONNECTED) 40] delete /test1
[zk: localhost:2181(CONNECTED) 41] ls
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 42] ls /
[admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, test20000000016, test20000000017, test3, test40000000019, test40000000020, test5, test6, zookeeper]
- 删除持久序号节点
[zk: localhost:2181(CONNECTED) 43] delete /test20000000016
[zk: localhost:2181(CONNECTED) 45] ls /
[admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, test20000000017, test3, test40000000019, test40000000020, test5, test6, zookeeper]
- 更新节点数据
[zk: localhost:2181(CONNECTED) 46] get /test3
ll3
[zk: localhost:2181(CONNECTED) 47] get -s /test3
ll3
cZxid = 0xa4
ctime = Sun Jan 01 20:47:47 HKT 2023
mZxid = 0xa4
mtime = Sun Jan 01 20:47:47 HKT 2023
pZxid = 0xa4
cversion = 0
dataVersion = 0 # 数据版本0
aclVersion = 0
ephemeralOwner = 0x10002ee9e300000
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 48] set -e /test3 ll333
org.apache.commons.cli.UnrecognizedOptionException: Unrecognized option: -e
[zk: localhost:2181(CONNECTED) 49] set /test3 ll333
[zk: localhost:2181(CONNECTED) 50]
[zk: localhost:2181(CONNECTED) 50] get /test3
ll333
[zk: localhost:2181(CONNECTED) 51] get -s /test3
ll333
cZxid = 0xa4
ctime = Sun Jan 01 20:47:47 HKT 2023
mZxid = 0xae
mtime = Sun Jan 01 21:22:07 HKT 2023
pZxid = 0xa4
cversion = 0
dataVersion = 1 # 数据版本加1
aclVersion = 0
ephemeralOwner = 0x10002ee9e300000
dataLength = 5
numChildren = 0
zk: localhost:2181(CONNECTED) 58] create -e /test3 ll3
Created /test3
[zk: localhost:2181(CONNECTED) 59] set /test3 ll3+1
[zk: localhost:2181(CONNECTED) 60] get /test3
ll3+1
[zk: localhost:2181(CONNECTED) 61] ls /
[admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, test20000000017, test3, test40000000019, test40000000020, test5, test6, zookeeper]
[zk: localhost:2181(CONNECTED) 62] get -s /test3
ll3+1
cZxid = 0xb3
ctime = Sun Jan 01 21:24:35 HKT 2023
mZxid = 0xb4
mtime = Sun Jan 01 21:24:48 HKT 2023
pZxid = 0xb3
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x10002ee9e300000
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 63] delete -v 1 /test3
[zk: localhost:2181(CONNECTED) 64] ls /
[admin, brokers, cluster, config, consumers, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, test20000000017, test40000000019, test40000000020, test5, test6, zookeeper]
6 Gurator 客户端
是 java写的一个api 库,可以更方便的在代码中调用。而不是 使用zkCli
就zkCli能操作的。Gurator都封装好方法了。调用就完事了。
7 zk 的分布式锁
7.1 zk中锁的种类
- 读锁: 读锁是共享的,获取读锁的前提是没有写锁
- 写锁:写锁是排他的,获取写锁的前提是没有任何锁
7.2 读锁的实现
- 创建一个临时序号节点,节点的数据是read. 表示是读锁。
- 获取zk中序号比自己小的所有节点。如果最小的节点是读锁。则上锁成功。因为如果最小的锁是读锁。后面不可能会有写锁。读锁共享。所以可以直接上锁。如果最小的节点是写锁。上锁失败,监听最小的节点。阻塞,如果最小节点释放了。然后重新执行第二步。
但是这样有一个坏处,并发的时候。多个客户端都监听 最小的节点,最小的节点释放之后会触发所有的客户端 重新获取锁。
也叫惊群效应。
解决方案:并发的操作,不去监听最小的,而是监听自己的上一个。这样就会按照请求的顺序依次获取锁。像个链表一样。
7.3 写锁的实现
- 创建一个临时序号节点,节点的数据是write.
- 获取zk中所有的子节点。
- 判断自己是不是最小的节点,如果是,上锁成功,如果不是,上锁失败,监听上一个节点。直到自己是最小的节点。
8 zk的watch机制
就是需要监听某一个节点的事件。类似于监听器。如果更新或删除了执行某些动作。
一个客户端修改了数据,另一个客户端会收到数据被修改的时间通知。
如果想监听是单次生效的。使用 get -w /test-watch
监听当前目录 ls -w /
监听当前目录及子目录 ls -w -R /
9 zk集群
9.1 伪集群,在一台服务器上创建四个目录。目录下分别有myid文件,保存id
└─# pwd 2 ⚙
/usr/local/zookeeper/zkdata
(base) ┌──(root
标签:zookeeper,zk,Zookeeper,---,2181,CONNECTED,节点,localhost,分布式
From: https://www.cnblogs.com/clllll/p/17018553.html