zookeeper 分布式共享锁的流程图

1分布式共享锁的流程图

 

原理

package cn.itcast.bigdata.zklock;

import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class DistributedClientLock {

	// 会话超时
	private static final int SESSION_TIMEOUT = 2000;
	// zookeeper集群地址
	private String hosts = "mini2:2181,mini3:2181,mini4:2181";
	// 父节点
	private String groupNode = "/locks";
	// 子节点
	private String subNode = "/locks/sub";
	//锁状态标识位
	private String haveLock ="/haveLock";

	private ZooKeeper zk;
	// 记录自己创建的子节点路径
	private volatile String thisPath;

	/**
	 * 连接zookeeper
	 */
	public void connectZookeeper(final String hostName) throws Exception {
		zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {
			public void process(WatchedEvent event) {
				try {

					// 判断事件类型,此处只处理子节点变化事件
					if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals(groupNode)) {
						// 获取子节点,并对父节点进行监听
						List<String> childrenNodes = zk.getChildren(groupNode, true);
						String thisNode = thisPath.substring((groupNode + "/").length());
						// 去比较是否自己是最小id
						Collections.sort(childrenNodes);
						if (childrenNodes.indexOf(thisNode) == 0) {
							// 访问共享资源处理业务,并且在处理完成之后删除锁
							doSomething(hostName);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		//
		//	判断锁状态标识位节点是否存在,没有就创建
		if(zk.exists(haveLock, false)==null) zk.create(haveLock,"0".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT) ;
		
		// 1、程序一进来就先注册一把锁到zk上
		thisPath = zk.create(subNode, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

		

		// 从zk的锁父目录下,获取所有子节点,并且注册对父节点的监听
		List<String> childrenNodes = zk.getChildren(groupNode, true);

		// 如果争抢资源的程序就只有自己,且锁没有被使用,则可以直接去访问共享资源
		byte[] data = zk.getData(haveLock, false, null);
		String isHaveLock=new String(data);
		//如果只有自己就去获取锁
		if (childrenNodes.size() == 1&&isHaveLock.equals("0")) {
			doSomething(hostName);
		}
	}

	/**
	 * 处理业务逻辑,并且在最后释放锁
	 */
	private void doSomething(String hostName) throws Exception {
		try {
			System.out.println(hostName+"  get lock: " + thisPath);
			//修改锁状态标志
			zk.setData(haveLock, "1".getBytes(), -1);
			// do something
		} finally {
			System.out.println(hostName+"  finished  doSomething");
			// 释放锁
			zk.delete(this.thisPath, -1);
			//修改锁状态标志
			zk.setData(haveLock, "0".getBytes(), -1);
			//并重新注册锁
			thisPath = zk.create(subNode, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
			
			System.out.println(hostName+"  注册新锁: "+thisPath);
			// wait一小会,便于观察
			Thread.sleep(new Random().nextInt(3000));
		}
	}

	public static void main(String[] args) throws Exception {
		DistributedClientLock dl = new DistributedClientLock();
		dl.connectZookeeper("hostName");
		Thread.sleep(Long.MAX_VALUE);
	}

}

测试

public class Test {
    public static void main(String[] args) throws Exception {
        DistributedClientLock dl = new DistributedClientLock();
        dl.connectZookeeper("mini2");
        Thread.sleep(Long.MAX_VALUE);
    }
}
public class Test2 {
    public static void main(String[] args) throws Exception {
        DistributedClientLock dl = new DistributedClientLock();
        dl.connectZookeeper("mini3");
        Thread.sleep(Long.MAX_VALUE);
    }
}

public class Test3 {
    public static void main(String[] args) throws Exception {
        DistributedClientLock dl = new DistributedClientLock();
        dl.connectZookeeper("mini4");
        Thread.sleep(Long.MAX_VALUE);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值