Zookeeper使用

  1. zookeeper 官网地址:http://zookeeper.apache.org/java

  2. zookeeper 数据模型node

       zookeeper 表现为一个分层的文件系统目录树结构(不一样于文件系统的是,节点能够有本身的数据,而文件系统中的目录节点只有子节点)apache

       

每一个节点均可以有关联的数据和子节点  缓存

ZooKeeper树中的节点称做znodeznode会维护一个包含数据修改和ACL修改版本号的Stat结构体,这个结构体还包含时间戳字段。版本号和时间戳让ZooKeeper能够校验缓存,协调更新。每次修改znode数据的时候,版本号会增长。客户端获取数据的同时,也会取得数据的版本号。执行更新或者删除操做时,客户端必须提供版本号。若是提供的版本号与数据的实际版本不匹配,则更新操做失败。session

版本号有三种:versionznode数据修改的次数)、cversionznode子节点修改的次数),以及aversionznodeACL修改次数)。分布式

主节点是临时节点 EPHEMERAL、EPHEMERAL_SEQUENTIAL 不能构建子节点ide

Zookeeper 中最有特点且最不容易理解的是监视(Watches)。Zookeeper 全部的读操做——getData()getChildren(), 和 exists() 都 能够设置监视(watch),监视事件能够理解为一次性的触发器this

3.spa

判断当前客户端 LockID 是否为最小 ,最小就得到锁 执行定时任务code

public class ZKClient implements Watcher {
       private String hosts;
private String ownerPath;
private long lockID;
public long getLockID() {
return lockID;
}
private  ZooKeeper zookeeper = null;
private static final String rootNode="/hnm";
public ZooKeeper getZookeeper() {
return zookeeper;
}
public void setZookeeper(ZooKeeper zookeeper) {
this.zookeeper = zookeeper;
}
private static final int sessionTimeOut = 30000;//30s会话延时
private CountDownLatch connectSemaphore = new CountDownLatch(1);//同步计数器
public String getHosts() {
return hosts;
}
public void setHosts(String hosts) {
this.hosts = hosts;
}
public void initZookeeper(){
try {
 this.zookeeper = new ZooKeeper(hosts, sessionTimeOut, this);
     connectSemaphore.await(); 
     Stat rootstat = zookeeper.exists(rootNode,false);
 if(rootstat == null){
       zookeeper.create(rootNode, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
 }
 if(this.ownerPath ==null || zookeeper.exists(this.ownerPath,false) == null){
 this.ownerPath =  zookeeper.create(rootNode+"/lock-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}else{
 zookeeper.delete(this.ownerPath, -1);
 }
 this.lockID = Long.parseLong(this.ownerPath.substring(this.ownerPath.lastIndexOf("-")+1));
} catch (Exception e) {
   e.printStackTrace();
}
 }
public String getOwnerPath() {
return ownerPath;
}
@Override
public void process(WatchedEvent event) {
  KeeperState state = event.getState();
  if(KeeperState.SyncConnected == state){
  connectSemaphore.countDown();
  }else if(KeeperState.Expired == state || KeeperState.Disconnected == state){
  this.initZookeeper();
  }
}
}
/**
 * 分布式锁
 * @author Administrator
 *
 */
public class DistributeLock {
 private static final Logger LOG = Logger.getLogger(DistributeLock.class);
private ZKClient zkclient;
public void setZkclient(ZKClient zkclient) {
this.zkclient = zkclient;
}
private static final String rootNode = "/hnm";
/**
 * 是否获得分布式锁
 * 判断当前zookeeper客户端session 是不是最小的 若是是 就表示拿到分布式锁
 * @return
 */
public  boolean isGetLock(){
ZooKeeper  client =zkclient.getZookeeper();
boolean flag=true;
try {
 System.out.println(zkclient.getOwnerPath());
 List<String> list = client.getChildren(rootNode, false);
 long ownerID = zkclient.getLockID();
 for(String str:list){
System.out.println(str);
long id = Long.parseLong(str.substring(str.lastIndexOf("-")+1));
if(id < ownerID){
flag= false;
break;
}
System.out.println(id);
}
} catch (Exception e) {
LOG.error(e);
}
return flag;
}
}

4.有可能出现的问题 

    定时任务间隔时间过短: 某一个客户端断开连接  但定时任务正在执行  。另外一个客户端发现lockid变成最小的,也但是执行

相关文章
相关标签/搜索