此处的编程的目的是为了实现分布式共享锁,当很多台客户端访问同一个资源时,就需要共享锁来实现合理的访问秩序;
那么在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); } }