此处的编程的目的是为了实现分布式共享锁,当很多台客户端访问同一个资源时,就需要共享锁来实现合理的访问秩序;
那么在zookeeper下的共享锁的实现如下代码
编程思想:
1.每个申请访问资源的客户端都要在zookeeper上注册一个临时序列节点,
2.比较每个节点的大小,最小的可以获得访问权限,访问结束后,结束程序或者重新申请访问,这样就要先删除该节点
3.其他客户端监听父节点是否有NodeChildrenChanged事件通知并且事件路径为父节点
4.收到通知后,获取父节点所有子节点,并与本节点进行对比,是否为最小
代码如下所示:
package bigdata.zksharelock;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import bigdata.zkserertest.zkClientss;
public class ShareLock {
private static final String connectString = "lanc05:2181,lanc06:2181,lanc07:2181";
private static final int sessionTimeout =2000;
private static final String parent = "/locks";
private static final String child = "/lock";
static ZooKeeper zk =null;
private volatile String currentlock;
public static void testparent() throws Exception{
//判断是否存在这个父目录
Stat exists = zk.exists(parent, false);
//如果不存在则创建
if(exists == null){
zk.create(parent, "IIIII".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(" not exit ,then create----");
}
}
public void getconnect() throws Exception {
zk =new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
try {
System.out.println(event.getType()+ "+++++++"+ event.getPath());
//监听事件为子节点发生变化,并且发生的路径为/locks,则判断的所需事件
if(event.getType()==EventType.NodeChildrenChanged && event.getPath().equals(parent)){
//dosometing
System.out.println(" get event");
getlock();
}
} catch (Exception e) {
}
}
});
currentlock = zk.create(parent+child, "lock".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// Thread.sleep(new Random().nextInt(1000));
List<String> sonlocks = zk.getChildren(parent, true);
// if(sonlocks.size() == 1){
// clientwork();
// currentlock = zk.create(parent+child, "lock".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
//
// }
}
/**
* 获取所有锁,排序并判断是不是最小锁
* @throws Exception
*/
public void getlock() throws Exception{
//获取所有的子节点的信息,并监听父节点
List<String> locks = zk.getChildren(parent, true);
Collections.sort(locks);
System.out.println(locks.size() + " v " );//+ lockpath
String cutlock = currentlock.substring((parent+ "/").length());
if(locks.get(0).equals(cutlock)){
System.out.println(currentlock + " get lock -----");
//dosomething
clientwork();
//注册一个临时序列节点作为锁
currentlock = zk.create(parent+child, "lock".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}else{
System.out.println( currentlock + " not get lock ****");
}
}
/**
*
*处理业务逻辑,或者访问共享资源,然后删除自己的锁
* @throws Exception
*/
public void clientwork() throws Exception {
System.out.println("client starts working .....");
Thread.sleep(1000);
zk.delete(currentlock, -1);
}
/**
* 逻辑思路
* 1.程序节点启动时到ZK上注册一个临时序列节点,并监听父节点
* 2.获取父节点下的所有子节点,比较序号大小
* 3.序号最小的获得锁,去访问共享资源,访问完后删除这个节点,相当于释放锁,并重新注册一个节点
* 4.其他程序节点会收到事件通知,然后到zk上获取锁
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//创建zk链接并监听父节点
ShareLock zc= new ShareLock();
zc.getconnect();
//先判断着个父目录是否存在,不存在就创建
//zc.testparent();
//获取共享锁,并监控父节点
//zc.getlock();
//zc.clientwork();
Thread.sleep(Long.MAX_VALUE);
}
}