Zookeeper(一) —— 环境搭建
一、概述
集中式 向 分布式演变,高并发、海量存储
应用场景:
* 数据发布、订阅的两种方式:推模式、拉模式
* 命名服务
* 分布式协调/通知(心跳检测)
* 负载均衡
自增长id和uuid的缺点,前者只能在单表中使用,后者可在分布式环境使用,但不易于理解、寻找规律
二、基本概念
1、集群中的角色:
* Leader
* Follower
* Observer
2、会话
客户端与Zookeeper的连接,其连接是通过TCP长连接,保持会话,客户端会向Zookeeper端上报心跳。会话也被叫做Session
3、版本
版本的作用是进行分布式锁控制,锁分为两种,悲观锁和乐观锁
悲观锁适合并发竞争激烈的场景,能避免数据不一致的情况,上一个事务没完成,下一个事务不能开始。乐观锁的并发控制是,加入版本号,每次读取记录时首先会获得版本号,插入数据时,也会将版本号带到参数中,若更新失败,说明其他事务已经修改过数据,会抛出异常给客户端,让其进行处理(重试)
version 当前数据内容节点版本号
cversion 当前数据子节点版本号
aversion 当前数据节点ACL变更版本号
4、节点
服务器(节点)
数据模型中的节点
5、watcher
客户端可以在zookeeper中注册watcher,当zookpeer上的内容改变时,会通知客户端获取
6、ACL权限控制
CREATE 创建子节点的权限
READ 读取节点数据、子节点列表的权限
WRITE 更新节点数据的权限
DELETE 删除子节点的权限
ADMIN 设置节点ACL权限
三、环境安装
1、创建文件夹
/opt 用来安装自己的应用软件
/var 用来存放日志输出
2、下载zookeeper
wget 下载链接
3、进行配置
(1)修改Zoo.cfg
dataDir 是用来存放数据快照
clientPort 对外提供的端口号,默认2181
server.id=ip:port:port
server.1=ip:port:port
server.2=ip:port:port
server.3=ip:port:port
(2)在/var/zookeeper中创建myid,内容为id编号,如1
4、启动
export ZK_HOME = /../zookeeper
export PATH=\(PATH:\)ZK_HOME/bin
Zookeeper/bin zkServer.sh start
telnet ip port(2181)
输入 stat 查看状态
四、zk命令
1、启动客户端连接到服务器
zkCli.sh -server serverip:2181
help
quit
ls / //列出节点
create /path content
get /path //查看数据
set /path conent //设置数据
delete /path //删除一个节点
rmr /a //递归删除所有节点
五、通过API访问zk
1、获取根下的目录
(1) 导入依赖包
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
(2)测试代码
fonxian1 对应的是zk服务器的ip地址
@org.junit.Test
public void ls() throws Exception{
ZooKeeper zk = new ZooKeeper("fonxian1:2181",10000,null);
List<String> list = zk.getChildren("/",false);
for(String str:list){
System.out.println(str);
}
}
2、递归获取根下所有文件名
@org.junit.Test
public void lsAll() {
try {
ls("/");
} catch (Exception e) {
e.printStackTrace();
}
}
public void ls(String path) throws Exception {
ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
List<String> list = zk.getChildren(path, false);
if (list == null || list.isEmpty()) {
return;
}
for (String str : list) {
if ("/".equals(path)) {
System.out.println(path + str);
ls(path + str);
} else {
System.out.println(path + "/" + str);
ls(path + "/" + str);
}
}
}
3、添加数据
@org.junit.Test
public void setData () {
try{
ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
zk.setData("/a","fonxian".getBytes(),2);
}catch (Exception e){
e.printStackTrace();
}
}
出现版本号错误的提示
org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /a
at org.apache.zookeeper.KeeperException.create(KeeperException.java:115)
at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
at org.apache.zookeeper.ZooKeeper.setData(ZooKeeper.java:1327)
at com.fonxian.ZookeepTest.setData(ZookeepTest.java:47)
原因是Zookeeper服务器中/a的版本号为0,将代码中的版本号设置为0,即可执行成功
[zk: 127.0.0.1(CONNECTED) 0] get /a
tom
cZxid = 0x200000002
ctime = Sun Mar 18 15:49:45 CST 2018
mZxid = 0x200000002
mtime = Sun Mar 18 15:49:45 CST 2018
pZxid = 0x20000000f
cversion = 3
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 3
4、添加临时节点
create [-s] [-e] path data acl
参数s ,表示序列节点,会在父节点下创建一个10个0+父节点名的节点
参数e,表示临时节点,临时节点在会话结束时会被删除,在leader选举中扮演重要作用
@Test
public void setTempData() {
try {
ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null);
zk.create("/a/t","fonxian".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("hello");
} catch (Exception e) {
e.printStackTrace();
}
}
5、使用观察者
观察者的作用在于,当数据发生修改,服务器会通知客户端数据修改,每次注册,只会通知一次。
@Test
public void testWatch(){
try {
final ZooKeeper zk = new ZooKeeper("fonxian1:2181", 50000, null);
Watcher w = new Watcher() {
public void process(WatchedEvent watchedEvent) {
try{
System.out.println("data change");
byte[] newData = zk.getData("/a",this,null);
System.out.println("new data = "+new String(newData));
}catch (Exception e){
e.printStackTrace();
}
}
} ;
byte[] data = zk.getData("/a",w,null);
System.out.println(new String(data));
while(true){
}
} catch (Exception e) {
e.printStackTrace();
}
}
关于作者
后端程序员,五年开发经验,从事互联网金融方向。技术公众号「清泉白石」。如果您在阅读文章时有什么疑问或者发现文章的错误,欢迎在公众号里给我留言。