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變成最小的,也但是執行

相關文章
相關標籤/搜索