简介
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它为分布式应用提供一致性服务。
安装
使用Docker安装ZooKeeper教程如下:
首先下载镜像:
docker pull zookeeper:3.7.0
创建ZooKeeper的配置文件目录及配置文件:
mkdir -p /mydata/zookeeper/conf/
cd /mydata/zookeeper/conf/
touch zoo.cfg
配置文件zoo.cfg:
vi zoo.cfg
#insert 插入如下数据
# 设置心跳时间,单位毫秒
tickTime=2000
# 存储内存数据库快照的文件夹
dataDir=/tmp/zookeeper
# 监听客户端连接的端口
clientPort=2181# wq! 进行保存退出
运行ZooKeeper容器:
docker run -p 2181:2181 --name zookeeper \
-v /mydata/zookeeper/conf/zoo.cfg:/conf/zoo.cfg \
-d zookeeper:3.7.0
可通过如下命令查询容器信息:
docker ps
进入容器内部:
docker exec -it 2be9cc456c5a /bin/bash
使用zkCli命令连接ZooKeeper:
zkCli.sh -server 127.0.0.1:2181
再ZooKeeper中是通过znode-value的形式存储数据,znode可以理解为linux的目录,和linux一样 /目录就是ZooKeeper的根目录,通过ls命令可以查看znode:
ls /
创建znode:
查看根目录下znode,这里可以看到kwin已被创建:
读取znode中的数据:
修改数据:
删除znode:
Spring boot 集成
配置:
zookeeper:
address: 127.0.0.1:2181
timeout: 4000
配置类:
package com.kwin.test.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.CountDownLatch;
/**
* @author : wangkai
* @version V1.0
* @Package com.kwin.test.config
* @Description:
* @date 2021年06月21日 11:16
**/
@Slf4j
@Configuration
public class ZookeeperConfig {
@Value("${zookeeper.address}")
private String address;
@Value("${zookeeper.timeout}")
private int timeout;
@Bean(name = "zkClient")
public ZooKeeper zkClient(){
ZooKeeper zooKeeper=null;
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
//连接成功后,会回调watcher监听,此连接操作是异步的,执行完new语句后,直接调用后续代码
// 可指定多台服务地址 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
zooKeeper = new ZooKeeper(address, timeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
if(Event.KeeperState.SyncConnected == event.getState()){
//如果收到了服务端的响应事件,连接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
log.info("初始化ZooKeeper连接成功... {}", zooKeeper.getState());
}catch (Exception e){
log.error("初始化ZooKeeper连接异常... {}", e);
}
return zooKeeper;
}
}
创建znode:
package com.kwin.test.util;
import java.nio.charset.StandardCharsets;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import lombok.extern.slf4j.Slf4j;
/**
* @author : wangkai
* @version V1.0
* @Package com.kwin.test.util
* @Description:
* @date 2021年06月21日 11:48
**/
@SpringBootTest
@Slf4j
class ZkUtilTest {
@Autowired
private ZooKeeper zkClient;
@Test
public void create() throws KeeperException, InterruptedException {
String znode = "/kwin";
String data = "Hello world!";
zkClient.create(znode, data.getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
通过客户端可以查看:
读取znode:
package com.kwin.test.util;
import java.nio.charset.StandardCharsets;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import lombok.extern.slf4j.Slf4j;
/**
* @author : wangkai
* @version V1.0
* @Package com.kwin.test.util
* @Description:
* @date 2021年06月21日 11:48
**/
@SpringBootTest
@Slf4j
class ZkUtilTest {
@Autowired
private ZooKeeper zkClient;
@Test
public void get() throws KeeperException, InterruptedException {
String znode = "/kwin";
byte[] res = zkClient.getData(znode, false, new Stat());
log.info("res is {}", new String(res));
}
}
更新znode:
package com.kwin.test.util;
import java.nio.charset.StandardCharsets;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import lombok.extern.slf4j.Slf4j;
/**
* @author : wangkai
* @version V1.0
* @Package com.kwin.test.util
* @Description:
* @date 2021年06月21日 11:48
**/
@SpringBootTest
@Slf4j
class ZkUtilTest {
@Autowired
private ZooKeeper zkClient;
@Test
public void update() throws KeeperException, InterruptedException {
String znode = "/kwin";
String data = "Hello dog!";
//zk的数据版本是从0开始计数的。如果客户端传入的是-1,则表示zk服务器需要基于最新的数据进行更新。如果对zk的数据节点的更新操作没有原子性要求则可以使用-1.
//version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
zkClient.setData(znode, data.getBytes(StandardCharsets.UTF_8), -1);
byte[] res = zkClient.getData(znode, false, new Stat());
log.info("res is {}", new String(res));
}
}
删除znode:
package com.kwin.test.util;
import java.nio.charset.StandardCharsets;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import lombok.extern.slf4j.Slf4j;
/**
* @author : wangkai
* @version V1.0
* @Package com.kwin.test.util
* @Description:
* @date 2021年06月21日 11:48
**/
@SpringBootTest
@Slf4j
class ZkUtilTest {
@Autowired
private ZooKeeper zkClient;
@Test
public void delete() throws KeeperException, InterruptedException {
String znode = "/kwin";
zkClient.delete(znode, -1);
}
}