基于zookeeper的分布式锁实现
来源:互联网 发布:java开发实战经典答案 编辑:程序博客网 时间:2024/05/22 00:37
之前已经实现过基于redis的分布式锁
这次用zookeeper来实现.
原理:ZooKeeper有四种形式的目录节点,四种CreateMode
- PERSISTENT:持久化目录节点,存储的数据不会丢失。
- PERSISTENT_SEQUENTIAL:顺序自动编号的持久化目录节点,存储的数据不会丢失,并且根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名。
- EPHEMERAL:临时目录节点,一旦创建这个节点的客户端与服务器端口也就是session 超时,这种节点会被自动删除。
- EPHEMERAL_SEQUENTIAL:临时自动编号节点,一旦创建这个节点的客户端与服务器端口也就是session 超时,这种节点会被自动删除,并且根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名。
用EPHEMERAL_SEQUENTIAL即可实现分布式锁.当获取锁的时候,节点会自动增加,如果你的节点是最小的,那么你就获取锁.不然就等待.(只需等待比你大的节点是否还存在,如果不存在,重复获取)
代码
package demo.zookeeper.lock;import demo.zookeeper.AbstractZooKeeper;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.ZooDefs;import org.apache.zookeeper.ZooKeeper;import java.io.IOException;import java.util.Comparator;import java.util.List;/** * 基于Zookeeper的分布式锁 * Created by yuyufeng on 2017/8/22. */public class LockUtil { //锁失效时间10秒 private static final int TIME_OUT = 10000; private static final String HOST = "localhost:2181"; private static ZooKeeper zookeeper; private static String ROOT_PATH = "/lockdata"; static { try { zookeeper = new ZooKeeper(HOST, TIME_OUT, new AbstractZooKeeper()); try { //建立锁节点存放根目录 if (zookeeper.exists(ROOT_PATH, false) == null) { zookeeper.create(ROOT_PATH, "true".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (Exception e) {} } catch (IOException e) {} } /** * 获取一个锁 * @param key 同步监听对象 * @return */ public static boolean getLock(String key) { Long beginTime = System.currentTimeMillis(); try { if (zookeeper.exists(ROOT_PATH + "/" + key, false) == null) { zookeeper.create(ROOT_PATH + "/" + key, "true".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (KeeperException e) {} catch (InterruptedException e) {} String result = null; try { result = zookeeper.create(ROOT_PATH + "/" + key + "/", "true".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); } catch (KeeperException e) {} catch (InterruptedException e) {} result = result.substring(result.lastIndexOf("/") + 1, result.length()); return lockHandler(key, beginTime, result); } private static boolean lockHandler(String key, Long beginTime, String result){ List<String> list = null; try { list = zookeeper.getChildren(ROOT_PATH + "/" + key, false); } catch (KeeperException e) {} catch (InterruptedException e) {} if (list == null || list.size() == 0) { System.out.println(Thread.currentThread().getName()+"获取锁异常,失败!"); return false; } System.out.println("=========================================="); list.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.valueOf(o1) - Integer.valueOf(o2); } }); System.out.println(Thread.currentThread().getName()+"获取锁结果: " + result + " :" + list.get(0)); if (result.equals(list.get(0))) { System.out.println(Thread.currentThread().getName()+ROOT_PATH + "/" + key + " 获取锁成功"); return true; } //为获取锁失败,监听当前节点之前的节点,如之前的节点已经不存在,再次获取. String beforeNode = list.get(0); for (int i = 0; i < list.size(); i++) { if (result.equals(list.get(i))) { beforeNode = list.get(--i); break; } } //监听上一个节点5秒,如果上一个节点不存在,则再去获取锁 while ((System.currentTimeMillis() - beginTime) < 5000) { System.out.println(Thread.currentThread().getName()+" 正在监听节点 " + ROOT_PATH + "/" + key + "/" + beforeNode); try { if (zookeeper.exists(ROOT_PATH + "/" + key + "/" + beforeNode, false) == null) { return lockHandler(key, beginTime, result); } } catch (KeeperException e) {} catch (InterruptedException e) {} try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"之前的节点" + beforeNode + "未释放,放弃获取锁"); try { zookeeper.delete(ROOT_PATH + "/" + key + "/" + result, -1); } catch (InterruptedException e) {} catch (KeeperException e) {} return false; } /** * 删除一个监听对象下所有的节点 * @param key * @return */ public static boolean unLockNode(String key){ List<String> list = null; try { list = zookeeper.getChildren(ROOT_PATH + "/" + key, false); } catch (KeeperException e) { } catch (InterruptedException e) { } if (list != null) { for (String s : list) { try { zookeeper.delete(ROOT_PATH + "/" + key + "/" + s, -1); } catch (InterruptedException e) { } catch (KeeperException e) { } } } return true; } /** * 解锁当前获取锁的节点 * * @param key * @return * @throws InterruptedException * @throws KeeperException */ public static boolean unLock(String key) { System.out.println("开始解锁-------------"); List<String> list = null; try { list = zookeeper.getChildren(ROOT_PATH + "/" + key, false); } catch (KeeperException e) {} catch (InterruptedException e) {} if (list == null || list.size() == 0) { System.out.println(Thread.currentThread().getName()+"锁不存在,或已经被解锁,成功!"); return false; } System.out.println("=========================================="); list.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.valueOf(o1) - Integer.valueOf(o2); } }); try { zookeeper.delete(ROOT_PATH + "/" + key + "/" + list.get(0), -1); } catch (InterruptedException e) {} catch (KeeperException e) {} try { if (zookeeper.exists(ROOT_PATH + "/" + key + "/" + list.get(0), false) != null) { System.out.println(Thread.currentThread().getName()+" 解锁失败!"); return false; } } catch (KeeperException e) {} catch (InterruptedException e) {} System.out.println(Thread.currentThread().getName()+" 解锁成功!"); return true; } public static void main(String[] args) {// System.out.println(LockUtil.getLock("a1"));// System.out.println(LockUtil.unLock("a1")); new Thread() { @Override public void run() { System.out.println(LockUtil.getLock("a1")); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(LockUtil.unLock("a1")); }}.start(); new Thread() { @Override public void run() { System.out.println(LockUtil.getLock("a1")); System.out.println(LockUtil.unLock("a1")); }}.start(); new Thread() { @Override public void run() { System.out.println(LockUtil.getLock("a1")); }}.start(); LockUtil.unLockNode("a1"); }}
运行
==============================================================================================================================Thread-2获取锁结果: 0000000301 :0000000300Thread-0获取锁结果: 0000000300 :0000000300Thread-1获取锁结果: 0000000302 :0000000300Thread-0/lockdata/a1 获取锁成功Thread-2 正在监听节点 /lockdata/a1/0000000300trueThread-1 正在监听节点 /lockdata/a1/0000000301Thread-2 正在监听节点 /lockdata/a1/0000000300Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-2 正在监听节点 /lockdata/a1/0000000300Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-2 正在监听节点 /lockdata/a1/0000000300Thread-1 正在监听节点 /lockdata/a1/0000000301开始解锁-------------==========================================Thread-0 解锁成功!trueThread-2 正在监听节点 /lockdata/a1/0000000300==========================================Thread-2获取锁结果: 0000000301 :0000000301Thread-2/lockdata/a1 获取锁成功trueThread-1 正在监听节点 /lockdata/a1/0000000301Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-1 正在监听节点 /lockdata/a1/0000000301Thread-1之前的节点0000000301未释放,放弃获取锁false
使用zookeeper相对使用redis作为分布式锁的区别
阅读全文
1 0
- 基于zookeeper实现的分布式锁
- 基于zookeeper实现的分布式锁
- 基于zookeeper的分布式锁实现
- 基于zookeeper实现的分布式读写锁
- 基于zookeeper的分布式锁实现
- 基于Zookeeper的分布式锁实现
- 基于zookeeper的分布式锁实现
- ZooKeeper实战(五)基于zookeeper的分布式锁实现
- 分布式锁基于zookeeper实现
- 基于ZooKeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 基于zookeeper实现分布式锁
- 【Python】pip 国内镜像源
- maven学习笔记:命令行模式创建java_spark项目并运行示例程序
- 脚本语言
- php对redis操作详解[转]
- unity 调用jar Multiple dex files define
- 基于zookeeper的分布式锁实现
- 通过直接添加或者手动编译添加库,解决 library not found for -lxxx 等的问题
- 汇哲科技CISM每日一题
- C++编程音视频库ffmpeg的pts时间换算方法
- oracle11g scanip 负载均衡测试
- 临渊慕鱼,不如退而结网
- 三个电脑办公小技巧
- poj2796 (单调栈)
- Java基础总结(三)