一、简介
Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理、命名、分布式同步、集群管理、数据库切换等服务。它不适合用来存储大量信息,可以用来存储一些配置、发布与订阅等少量信息。Hadoop、Storm、消息中间件、RPC服务框架、分布式数据库同步系统,这些都是Zookeeper的应用场景。
Zookeeper集群中节点个数一般为奇数个(>=3),若集群中Master挂掉,剩余节点个数在半数以上时,就可以推举新的主节点,继续对外提供服务。
Zookeeper使用的数据结构为树形结构,根节点为"/"。Zookeeper集群中的节点,根据其身份特性分为leader、follower、observer。leader负责客户端writer类型的请求;follower负责客户端reader类型的请求,并参与leader选举;observer是特殊的follower,可以接收客户端reader请求,但是不会参与选举,可以用来扩容系统支撑能力,提高读取速度。
二、安装zookeeper
(1)安装
1、上传安装包到master并解压
tar -xvf zookeeper-3.4.6.tar.gz
2、配置环境变量
vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.4.6
export PATH=$PATH:$ZOOKEEPER_HOME/bin
source /etc/profile
3、修改配置文件
cd conf
cp zoo_sample.cfg zoo.cfg
修改
dataDir=/usr/local/soft/zookeeper-3.4.6/data
增加
server.0=master:2888:3888
server.1=node1:2888:3888
server.2=node2:2888:3888
4、同步到其它节点
scp -r zookeeper-3.4.6 node1:`pwd`
scp -r zookeeper-3.4.6 node2:`pwd`
配置node1和node2的环境变量
scp /etc/profile node1:/etc/
scp /etc/profile node2:/etc/
在所有节点执行
source /etc/profile
4、创建/usr/local/soft/zookeeper-3.4.6/data目录,所有节点都要创建
mkdir /usr/local/soft/zookeeper-3.4.6/data
在data目录下创建myid文件
vim myid
master,node1,node2分别加上0,1,2
5、启动zk,
zkServer.sh start 三台都需要执行
zkServer.sh status 查看状态
当有一个leader的时候启动成功,其他为follower
连接zk
zkCli.sh
zk 是一个目录结构 ,每个节点可以存数据,同时可以有子节点
zk shell
创建目录
create /test test
create /test/a 1
获取数据
get /test
ls /test
delete 只能删除没有子节点的节点
rmr /test 删除节点
重置zk
1、杀掉所有zk进程
kiil -9 pid
2、删除data目录下的version文件, 所有节点都要删除
rm -rf /usr/local/soft/zookeeper-3.4.6/data/version-2
2、启动zk
zkServer.sh start
(2)选举机制,其中一个为leader,其他为follower
三、简单命令
ls / 查找根目录
create /test abc 创建节点并赋值
get /test 获取指定节点的值
set /test cb 设置已存在节点的值
rmr /test 递归删除节点
delete /test/test01 删除不存在子节点的节点
四、Java连接zookeeper实现简单操作
(1)基本连接
public static void main(String[] args) throws IOException, InterruptedException {
String connectString= "master:2181,node1:2181,node2:2181";
int sessionTimeout=10*1000; //会话连接超时时间
ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("监听被执行");
}
});
System.out.println("-->"+zooKeeper);
zooKeeper.close();
}
(2)创建节点并赋值
替换上面的System.out.println("-->"+zooKeeper);
String path="/hadoop"; //创建节点名称
zooKeeper.create(path,"hadoop create".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//参数一为节点位置,参数二为插入节点中的内容,参数三身份认证 可以调用 Zookeeper中的枚举
/*参数四:
* # CreateMode.PERSISTENT 是指一个普通节点
* # PERSISTENT_SEQUENTIAL 是序列化的持久化节点
* # EPHEMERAL 表示临时节点
* # EPHEMERAL_SEQUENTIAL 表示临时序列化节点
*/
(3)输出所有的子节点
替换
List<String> children = zooKeeper.getChildren("/", false);
for (String child : children) {
System.out.println("child:"+child);
}
(4)监听节点变化
List<String> children = zookeeper.getChildren("/", new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("子节点发生变化:");
System.out.println(event.getPath()); //发生变化的目录
}
});
Thread.sleep(Long.MAX_VALUE); //线程睡眠
当创建一个新的节点后,会输出方法中的内容
(5)判断节点是否存在
Stat stat = zookeeper.exists("/spark", false);
if(stat == null){
System.out.println("节点不存在");
}else {
System.out.println(stat.getNumChildren()); //获取子节点的数量
}
(6)先判断节点是否存在,在输出节点中的内容
String path = "/hadoop";
Stat stat = zookeeper.exists(path, false);
if (stat == null){
System.out.println("节点不存在...");
}else {
// 获取节点的数据
byte[] data = zookeeper.getData("/hadoop", false, stat);
String value = new String(data);
System.out.println(value);
}
(7)先判断子节点是否存在,在输出每个子节点的内容
String path = "/hadoop";
Stat stat = zookeeper.exists(path, false);
if (stat == null){
System.out.println("节点不存在...");
}else {
List<String> children = zookeeper.getChildren(path, false);
for (String child : children) {
Stat child_stat = zookeeper.exists(path + "/" + child, false);
byte[] data = zookeeper.getData(path + "/" + child, false, child_stat);
System.out.println(new String(data));
}
}
(8)节点删除
// -1 表示不指定版本
zkCli.delete("/hadoop/yarn",-1);
zkCli.close();