zookeeper基本数据模型
- 是一个树形结构, 类似于前端开发中的tree.js
- 每一个节点都称之为znode, 它可以有子节点, 也可以有数据
- 每个节点分为临时节点和永久节点, 临时节点在客户端断开后消失
- 每个zk节点都有各自的版本号, 可以通过命令行来显示节点信息
- 每当节点数据发生变化, 那么该节点的版本号会累加(乐观锁)
- 删除/修改过时节点, 版本号不匹配则会报错
- 每个zk节点存储的数据不宜过大, 一般几K即可
- 节点可以设置权限acl, 可以通过权限来控制用户的访问
zookeeper常用命令
-
sh zkCli.sh -server ip:port : 客户端连接
-
ls : 类似于Linux中的ls
-
ls2 : 展示详细节点信息
-
stat : 节点状态信息
-
get : 读取节点数据
# 创建节点之后, zk为节点分配的节点id cZxid = 0x0 # 节点创建时间 ctime = Thu Jan 01 00:00:00 GMT 1970 # 修改后的节点id mZxid = 0x0 # 节点修改时间 mtime = Thu Jan 01 00:00:00 GMT 1970 # 子节点id pZxid = 0x0 # 子节点的version, 子节点发生变化时version会更改 cversion = -1 # 当前节点数据version, 数据发生变化时version会更改 dataVersion = 0 # 权限version, 权限发生变化时version会更改 aclVersion = 0 # ephemeralOwner = 0x0 # 数据长度 dataLength = 0 # 子节点个数 numChildren = 1
Session相关
- 客户端与服务端之间的连接存在会话
- 每个会话都可以设置一个超时时间
- 心跳结束, session就过期, session过期, 则临时节点znode会被删除
- 心跳机制 : 客户端向服务端的ping包请求
命令
-
创建节点 : create -[s][e] [nodeName][nodeData]
-s : 表示创建一个永久有序节点
-e : 表示创建一个临时节点
默认创建的是永久无序节点
-
修改节点值 : set [nodeName] [new Data] [version]
- 使用set nodeName newData可以直接进行更新
- 如果添加了version的话, 表示时乐观锁模式, 如果version版本不一致的话, 就会更新失败
-
删除节点 : delete [path] [version]
version和修改节点一样, 用于乐观锁
zookeeper四字命令
- zk可以通过它自身提供的简写命令和服务器进行交互
- 需要使用到nc命令, 安装 : yum install nc
- echo [command]|nc [ip] [port]
- 需要在zoo.cfg增加 "4lw.commands.whitelist=*"来增加四字命令的支持
常用四字命令:
- stat : 查看zk的状态信息, 以及mode
- ruok : 查看当前zkserver是否启动, 返回imok
- dump : 列出未经处理的会话和临时节点
- conf : 查看服务器配置信息
- cons : 展示连接到服务器的客户端信息
- envi : 环境变量
- mntr : 监控zk的健康信息
- wchs : 展示watch的信息
- wchc&wchp : session与watch及path与watch的信息
zookeeper特性
watcher机制
-
针对每个节点的操作, 都会有一个监督者 -> watcher
-
当监控的某个对象(znode)发生了变化, 则触发watcher事件
-
zk中的watcher是一次性的, 出发后立即销毁
-
父节点, 子节点增删改都能触发watcher
-
针对不同类型的操作, 触发的watcher事件也不同 :
- (子)节点创建事件
- (子)节点删除事件
- (子)节点数据变化事件
父节点watcher事件
- 通过get path [watch]设置watcher
- 父节点增删改操作触发watcher
- 子节点增删改触发watcher
- 创建父节点触发 : NodeCreated, 需要使用stat path watch设置
- 修改父节点触发 : NodeDataChanged
- 删除父节点 : NodeDelete
子节点watcher事件
- ls为父节点设置watcher, 创建子节点触发 : NodeChildrenChanged
- ls为父节点设置watcher, 删除子节点触发 : NodeChildrenChanged
- ls为父节点设置watcher, 修改子节点不触发事件
watcher使用场景
- 统一资源配置
ACL权限控制
- 针对节点可以设置相关读写等权限, 目的为了保障数据安全性
- 权限permissions可以指定不同的权限范围以及角色
- getAcl : 获取某个节点的acl权限信息
- setAcl : 设置某个节点的acl权限信息
- addauth : 输入认证授权信息, 注册(登录)时输入明文密码,zk中密码以加密方式存储
ACL的构成 :
zk的ACL通过[scheme : id : permissions]来构成权限列表
-
scheme : 代表采用的某种权限机制
- world : world下只有一个id, 即只有一个用户, 也就是anyone, 组合写法 world:anyone[permissions]
- auth : 代表认证登录, 需要注册用户有权限就可以, 格式 : auth:user:password:[permissions]
- digest : 需要对密码加密才能访问, 格式: digest:username:BASE64(SHA1(password)):[permissions]
- super : 代表超级管理员, 拥有所有的权限
-
id : 代表允许访问的用户
- 当设置ip为指定的ip地址, 此时限制ip进行访问
-
permissions : 权限组合字符串(cdrwa)
- CREATE : 创建子节点
- DELETE : 删除子节点
- READ : 获取节点/子节点
- WRITE : 设置节点数据
- ADMIN : 设置权限
命令
-
world:anyone:cdrwa
- crdwa可以任意组合
-
auth:user:pwd:cdrwa
digest:user:BASE64(SHA1(pwd)):cdrwa
添加用户(登录) : addauth digest user:pwd
-
digest
-
ip:[ip addr] cdrwa : 针对ip设置权限
-
super超级管理员
- 修改zkServer.sh增加super管理员
- 重启zk Server
ACL使用场景
- 开发/测试环境分离
- 生产环境上控制指定ip的服务可以访问相关节点, 防止混乱
Java原生API操作Zookeeper
Maven依赖:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<!-- 版本号自行选择 -->
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkClient.version}</version>
</dependency>
代码中使用到的配置:
public static final String ZK_PATH = “192.168.72.135:2181,192.168.72.136:2181,192.168.72.137:2181”;
public static final int TIMEOUT = 30000;
建立连接
ZooKeeper zooKeeper = new ZooKeeper(ZkConfig.ZK_PATH, ZkConfig.TIMEOUT, new ZkConnect());
创建节点
同步创建节点:
/**
* 同步创建Zk节点
* 同步或者异步创建节点,都不支持子节点的递归创建,异步有一个callback函数
* 参数:
* path:创建的路径
* data:存储的数据的byte[]
* acl:控制权限策略
* Ids.OPEN_ACL_UNSAFE --> world:anyone:cdrwa
* CREATOR_ALL_ACL --> auth:user:password:cdrwa
* createMode:节点类型, 是一个枚举
* PERSISTENT:持久节点
* PERSISTENT_SEQUENTIAL:持久顺序节点
* EPHEMERAL:临时节点
* EPHEMERAL_SEQUENTIAL:临时顺序节点
*/
private void createNodeSync(String path, String value, CreateMode createMode) throws Exception {
zooKeeper.create(path, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
}
除了同步创建节点之外, zookeeper也支持异步创建节点
获取节点数据
// 获取节点数据之后, stat用于保存当前节点的状态信息
Stat stat = new Stat();
byte[] data = zooKeeper.getData("/qiyexue", false, stat);
System.out.println(new String(data));
获取子节点
List<String> children = zooKeeper.getChildren("/qiyexue", false);
这里就简单列一些api, 实际开发中一般也很少用原生API去操作zookeeper, 一般都是使用客户端操作
curator操作zookeeper
一些常用操作, 放到了我的github上面, 地址 : https://github.com/564660143/zookeeper.git