zookeeper的API简单编程三---分布式共享锁的实现

此处的编程的目的是为了实现分布式共享锁,当很多台客户端访问同一个资源时,就需要共享锁来实现合理的访问秩序;

那么在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);
	}
}

猜你喜欢

转载自blog.csdn.net/hubbybob1/article/details/80683011