-
一.zookeeper概述
- 1.管理大量主机的协同服务。
- 2.分布式应用,实现分布式读写技术。
- 3.zk提供的服务
- Naming service //按名称区分集群中的节点.
- Configuration management //对加入节点的最新化处理。
- Cluster management //实时感知集群中节点的增减.
- Leader election //leader选举
- Locking and synchronization service //修改时锁定数据,实现容灾.
- Highly reliable data registry //节点宕机数据也是可用的。
-
二.zookeeper安装
1.jdk2.下载zookeeper-3.4.9.tar.gz
3.tar开
4.符号连接环境变量
$>ln -s zookeeper-3.4.9 zk5.配置zk,复制zoo.cfg.sample–>zoo.cfg
[zk/conf/zoo.conf]
# The number of milliseconds of each tick
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/centos/zookeeper
clientPort=21816.启动zk服务器
$>bin/zkServer.sh start7.验证zk
$>netstat -anop | grep 2181 -
三.zookeeper命令操作
$>zkCli.sh -server s201:2181 //进入zk命令行
$zk]help //查看帮助
$zk]quit //退出$zk]create /a tom //对于zk的目录结构来说,整个是树状结构,全部都为路径path,每个路径会携带数据,/a路径携带的数据为tom
Note: 当创建path的时候,必须存在父节点才可以创建,如果没有就会报错。例如:create /a/a1/a2 kaola Node does not exist: /a/a1/a2
$zk]get /a //查看数据
$zk]ls / //列出节点
$zk]set /a tom //设置数据
$zk]delete /a //删除一个节点
$zk]rmr /a //递归删除所有节点。 -
四.通过api访问zk
-
1.添加依赖
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.5</version> </dependency>
-
2.代码编写
package com.kaola.zkTest;
import org.apache.zookeeper.ZooKeeper;
import java.util.List;
public class ZkDemo {
public static void main(String[] args) throws Exception{
lsAll();
}
/**
* set的使用
* @throws Exception
*/
public static void setData() throws Exception{
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
zooKeeper.setData("/a","kaola".getBytes(),2); //需要传递版本version,这是为了并发时,防止恶意篡改数据,而且版本号要与zk中一致
}
/**
* 输出跟路径下的子节点
* @throws Exception
*/
public static void ls() throws Exception{
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
List<String> list = zooKeeper.getChildren("/",null);
for (String s : list){
System.out.println(s);
}
}
/**
* 递归输出
* @throws Exception
*/
public static void lsAll() throws Exception {
ls("/");
}
/**
* 递归输出路径的递归方法
* @param path
* @throws Exception
*/
public static void ls(String path) throws Exception{
System.out.println(path);
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
List<String> list = zooKeeper.getChildren(path,null);
if (list == null || list.isEmpty()){
return;
}
for (String s : list){
if (path.equals("/")){
ls(path+s);
}else {
ls(path+"/"+s);
}
}
}
}
创建节点需要注意事项:
/**
* 创建临时节点
* @throws Exception
*/
public static void create() throws Exception{
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
zooKeeper.create("/b","tom".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
}
注:create的api需要传入四个参数,第三个参数需要传递一个ACL,需要去ZooDefs.Ids中去寻找相应的ACL类型,而第四个参数需要传递节点类型,直接去CreateMode中去寻找就可以
public interface Ids {
/**
* This Id represents anyone.
*/
public final Id ANYONE_ID_UNSAFE = new Id("world", "anyone");
/**
* This Id is only usable to set ACLs. It will get substituted with the
* Id's the client authenticated with.
*/
public final Id AUTH_IDS = new Id("auth", "");
/**
* This is a completely open ACL .
*/
public final ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList<ACL>(
Collections.singletonList(new ACL(Perms.ALL, ANYONE_ID_UNSAFE)));
/**
* This ACL gives the creators authentication id's all permissions.
*/
public final ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList<ACL>(
Collections.singletonList(new ACL(Perms.ALL, AUTH_IDS)));
/**
* This ACL gives the world the ability to read.
*/
public final ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList<ACL>(
Collections
.singletonList(new ACL(Perms.READ, ANYONE_ID_UNSAFE)));
}
/***
* CreateMode value determines how the znode is created on ZooKeeper.
*/
public enum CreateMode {
/**
* The znode will not be automatically deleted upon client's disconnect.
*/
PERSISTENT (0, false, false),
/**
* The znode will not be automatically deleted upon client's disconnect,
* and its name will be appended with a monotonically increasing number.
*/
PERSISTENT_SEQUENTIAL (2, false, true),
/**
* The znode will be deleted upon the client's disconnect.
*/
EPHEMERAL (1, true, false),
/**
* The znode will be deleted upon the client's disconnect, and its name
* will be appended with a monotonically increasing number.
*/
EPHEMERAL_SEQUENTIAL (3, true, true);
-
五.zk架构
1.Client
从server获取信息,周期性发送数据给server,表示自己还活着。
client连接时,server回传ack信息。
如果client没有收到reponse,自动重定向到另一个server.2.Server
zk集群中的一员,向client提供所有service,回传ack信息给client,表示自己还活着。3.ensemble
一组服务器。
最小节点数是3.4.Leader
如果连接的节点失败,自定恢复,zk服务启动时,完成leader选举。5.Follower
追寻leader指令的节点。 -
六.znode
zk中的节点,维护了stat,由Version number, Action control list (ACL), Timestamp,Data length.构成.data version //数据写入的过程变化,每个节点都有一个版本号,当节点有变化时,版本号会自动增加
ACL //action control list,对于节点的认证机制,控制节点的读写权限
timestamp //主要是Zxid
data length //长度要限制在1MB -
七.节点类型
1.持久节点
client结束,还存在。2.临时节点
在client活动时有效,断开自动删除。临时节点不能有子节点。
leader推选是使用。3.序列节点
在节点名之后附加10个数字,主要用于同步和锁.
public enum CreateMode {
/**
* The znode will not be automatically deleted upon client's disconnect.
*/
PERSISTENT (0, false, false),
/**
* The znode will not be automatically deleted upon client's disconnect,
* and its name will be appended with a monotonically increasing number.
*/
PERSISTENT_SEQUENTIAL (2, false, true),
/**
* The znode will be deleted upon the client's disconnect.
*/
EPHEMERAL (1, true, false),
/**
* The znode will be deleted upon the client's disconnect, and its name
* will be appended with a monotonically increasing number.
*/
EPHEMERAL_SEQUENTIAL (3, true, true);
-
八.session
Session中的请求以FIFO执行,一旦client连接到server,session就建立了。sessionid分配client.client以固定间隔向server发送心跳,表示session是valid的,zk集群如果在超时时候,没有收到心跳,
判定为client挂了,与此同时,临时节点被删除。 -
九.Watches
观察。
client能够通过watch机制在数据发生变化时收到通知。
client可以在read 节点时设置观察者。watch机制会发送通知给注册的客户端。
观察模式只触发一次。
session过期,watch机制删除了。
/**
* 观察者
* 此方法,只有在第一次修改的时候会触发process中的方法,之后修改无效
* @throws Exception
*/
public static void testWatch1() throws Exception{
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
Stat stat = new Stat();
byte[] data = zooKeeper.getData("/a", new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("数据改了!!");
}
},stat);
System.out.println(new String(data));
while (true){
Thread.sleep(1000);
}
}
/**
* 观察者
* 此方法,保证每次修改都可以监听到
* @throws Exception
*/
public static void testWatch2() throws Exception{
ZooKeeper zooKeeper = new ZooKeeper("bigdata-pro01.kfk.com:2181",5000,null);
Stat stat = new Stat();
Watcher w = null;
w = new Watcher() {
@Override
public void process(WatchedEvent event) {
try {
System.out.println("数据改了");
zooKeeper.getData("/a",this,null);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
byte[] data = zooKeeper.getData("/a",w,stat);
System.out.println(new String(data));
while (true){
Thread.sleep(1000);
}
}