您的位置:首页 > 其它

zookeeper学习心得一:基础讲解---zk节点类型以及对节点的相应操作

2017-04-23 14:35 507 查看

zookeeper节点类型

持久节点(PERSISTENT)

所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点——不会因为创建该节点的客户端会话失效而消失。

持久顺序节点(PERSISTENT_SEQUENTIAL)

这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。

在创建节点的时候只需要传入节点 “/test_”,这样之后,zookeeper自动会给”test_”后面补充数字。

临时节点(EPHEMERAL)

和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。

这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失了,也要过一段时间,大概是10秒以内,可以试一下,本机操作生成节点,在服务器端用命令来查看当前的节点数目,你会发现客户端已经stop,但是产生的节点还在。

临时顺序节点(EPHEMERAL_SEQUENTIAL)

此节点是属于临时节点,不过带有顺序,客户端会话结束节点就消失。下面是一个利用该特性的分布式锁的案例流程。

(1)客户端调用create()方法创建名为“locknode/

guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。

(2)客户端调用getChildren(“locknode”)方法来获取所有已经创建的子节点,注意,这里不注册任何Watcher。

(3)客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点序号最小,那么就认为这个客户端获得了锁。

(4)如果在步骤3中发现自己并非所有子节点中最小的,说明自己还没有获取到锁。此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时注册事件监听。

(5)之后当这个被关注的节点被移除了,客户端会收到相应的通知。这个时候客户端需要再次调用getChildren(“locknode”)方法来获取所有已经创建的子节点,确保自己确实是最小的节点了,然后进入步骤3。

各类zookeeper java api的操作以及返回类型

创建会话

Zookeeper(String connectString,int sessionTimeout,Watcher watcher)

Zookeeper(String connectString,int sessionTimeout,Watcher watcher,boolean canBeReadOnly)

Zookeeper(String connectString,int sessionTimeout,Watcher watcher,long sessionId,byte[] sessionPasswd)

Zookeeper(String connectString,int sessionTimeout,Watcher watcher,long sessionId,byte[] sessionPasswd,boolean canBeReadOnly)

参数说明:

1. connectString : host:port[,host:port]指定的服务器列表,多个host:port之间用英文逗号分隔。还可以可选择的指定一个基路径,如果指定了一个基路径,则所有后续操作基于这个及路径进行。例如:188.12.23.25:2181,59.23.22.25:2181 像 [ip:端口号]这样的形式

2. sessionTimeOut – 会话超时时间。以毫秒为单位。客户端和服务器端之间的连接通过心跳包进行维系,如果心跳包超过这个指定时间则认为会话超时失效。一般设置为private static final int SESSION_TIMEOUT = 30000;

3. watcher – 指定默认观察者。如果为null表示不需要观察者。

4. canBeReadOnly – 是否支持只读服务。只当一个服务器失去过半连接后不能再进行写入操作时,是否继续支持读取操作。略

5. sessionId、SessionPassword – 会话编号 会话密码,用来实现会话恢复。

返回类型:上述返回的是一个zookeeper对象 ZooKeeper zk = new ZooKeeper(hosts, zktest.SESSION_TIMEOUT, this.wh);

**注意,整个创建会话的过程是异步的,构造方法会在初始化连接后即返回,并不代表真正建立好了一个会话,此时会话处于”CONNECTING”状态。

**当会话真正创建起来后,服务器会发送事件通知给客户端,只有客户端获取到这个通知后,会话才真正建立。

创建节点

String create(final String path,byte data[],List acl,CreateMode createMode); //同步方式创建

说明:返回的是该节点的路径名称,例如:/test/zh_1324578

void create(final String path,byte data[],List acl,CreateMode createMode,StringCallback cb,Object ctx);//异步方式创建

说明:此创建方式是通过回调函数来相应操作。

参数说明:

1. path 要创建的数据节点的路径

2. data [] 节点创建时初始数据内容

3. acl 节点acl安全策略

4. createMode 创建模式

(1)PERSISTENT 持久

(2)PERSISTENT_SEQUENTIAL 持久顺序

(3)EPHEMERAL 临时

(4)EPHEMERAL_SEQUENTIAL 临时顺序

5. cb 回调接口

6. ctx 传递对象,用来在回调方法中使用 通常是个上下文对象

注意:不支持递归创建,即不能在无父节点的情况下创建出子节点,尝试创建已经存在的节点将失败并抛出异常,在不需要进行任何权限控制时,只需传入Ids.OPEN_ACL_UNSAFE即可。

删除节点

public void delete(final String path,int version)

说明:无返回类型

public void delete(final String path,int version,VoidCallback cb,Object ctx)

说明:无返回类型

**注意:无法删除存在子节点的节点,即如果要删除一个节点,必须要先删除其所有子节点

获取结点信息

//同步方式

List getChildren(final String path,Watcher watcher)

List getChildren(String path,boolean watch)

List getChildren(final String path,Watcher watcher,Stat stat)

List getChildren(String path,boolean watch,Stat stat)

说明:上述返回的都是path路径下的节点名称

//异步方式

void getChildred(final String path,Watcher watcher,ChildrenCallback cb,Object ctx)

void getChildred(String path,boolean watch,ChildrednCallback cb,Object ctx)

void getChildred(final String path,Watcher watcher,Children2Callback cb,Object ctx)

void getChildred(String path,boolean watch,Children2Callback cb,Object ctx)

参数说明:

1. path 要创建的数据节点的路径

2. watcher 观察者,一旦在本子节点获取之后,子节点列表发生变更,服务器端向客户端发送消息,触发watcher中的回调。注意,仅仅是通知而已,如果需要新的子节点列表,需要自己再次去获取。允许传入null。

3. watch 表明是否需要注册一个Watcher。为true则通知默认到默认watcher,如果为false则不使用

4. cb 回掉函数

5. ctx 上下文对象

6. stat 指定数据节点的状态信息。用法是在接口中传入一个旧的stat变量,该stat变量会在方法执行过程中,被来自服务端响应的新stat对象替换。

获取节点数据

//同步方式

byte [] getData(final String path,Watcher watcher, Stat stat)

byte [] getData(String path,boolean watch, Stat stat)

//异步方式

void getData(final String path,Watcher watcher, DataCallback cb,Object ctx)

void getData(String path,boolean watch, DataCallback cb,Object ctx)

*可以通过注册Watcher进行监听,一旦该节点数据被更新会通知客户端

更新数据

//同步方式

Stat setData(final String path,byte data[],int version)//version可以传入-1,表明要基于最新版本进行更新操作

//异步方式

void setData(final String path,byte data[],int version,StatCallback cb,Object ctx)

检查节点是否存在

//同步方式

public Stat exists(final String path,Watcher watcher)

public Stat exists(String path,boolean watch)

//异步方式

public Stat exists(final String path,Watcher watcher,StatCallback cb,Object ctx)

public Stat exists(String path,boolean watch,StatCallback cb,Object ctx)

*可以通过注册Watcher进行监听,一旦节点被创建、删除、数据被更新都会通知客户端

zookeeper权限控制

addAuthInfo(String schema,byte [] auth)

参数说明;

schema 权限模式,可以是world auth digest ip super,我们使用digest

byte[] auth 权限控制标识,由”foo:123”.getByte()方式组成,后续操作只有auth值相同才可以进行

**注意删除操作,如果在增加节点时指定了权限,则对于删除操作,认为权限加在了子节点上,删除当前结点不需要权限,删除子节点需要权限。

代码:

import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class Demo {
private static final int TIMEOUT = 3000;
public static String  Url="21.190.126.190:2181";   // 自行修改为自己搭建的zookeeper的ip和端口号
public static void main(String[] args) throws IOException {
ZooKeeper zkp = new ZooKeeper("21.190.126.189:2181", TIMEOUT, null);
try {
// 创建一个EPHEMERAL类型的节点,会话关闭后它会自动被删除
zkp.create("/node1", "data1".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
if (zkp.exists("/node1", false) != null) {
System.out.println("node1 exists now.");
}
try {
// 当节点名已存在时再去创建它会抛出KeeperException(即使本次的ACL、CreateMode和上次的不一样)
zkp.create("/node1", "data1".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
} catch (KeeperException e) {
System.out.println("KeeperException caught:" + e.getMessage());
}

// 关闭会话
zkp.close();

zkp = new ZooKeeper(Url, TIMEOUT, null);
//重新建立会话后node1已经不存在了
if (zkp.exists("/node1", false) == null) {
System.out.println("node1 dosn't exists now.");
}
//创建SEQUENTIAL节点,其实在实际中,这几个节点的名称都是不一样的,自动增长node-0000000008,node-0000000009,node-0000000010
zkp.create("/node-", "same data".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);
zkp.create("/node-", "same data".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);
zkp.create("/node-", "same data".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);
List<String> children = zkp.getChildren("/", null);
System.out.println("Children of root node:");
for (String child : children) {
System.out.println(child);
}

zkp.close();
} catch (Exception e) {
System.out.println("发生错误:"+e.getMessage());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  zookeeper