排它锁(Exclusive Locks,简称X锁)又称之为独占锁,是一种基本的锁类型。排他锁的核心就是如何保证仅有一个线程获取到锁,并且在锁释放后,可以及时地通知到其他等待获取锁定的线程。下面使用ZK实现了一个简单的排它锁。
定义锁
在ZK下定义一个临时节点节点表示锁
/**排它锁节点**/
private final String EXCLUSIVE_LOCK = "/zk-demo/lock";
获取锁
在需要获取锁时,所有客户端都需要视图通过调用create()方法在ZK上创建这个临时节点。zk保证所有客户端中仅有一个客户端可以创建成功,如果创建成功的客户端则认为他获取了锁。同时没有获取到则需要向这个节点注册一个监听器,监听其他客户端释放锁。
释放锁
我们定义的锁是一个临时节点,有两种情况可以释放锁。
- 当前客户端发生宕机,也就是session断开则这个临时节点被移除。
- 正常业务逻辑执行完成后主动删除自己创建的临时节点。
无论在什么情况下移除了lock这个临时节点,ZK都会通知所有在/zk-demo节点上注册的子节点变更监听器。在客户端接收到通知时可以再次发起获取分布式锁的尝试
/** * 分布式锁服务接口,该接口定义了如下功能 * <ul> * <li> tryLock 一直等待锁</li> * <li> tryLock 等待一段时间,如果超时则会调用回调方法expire()</li> * </ul> * * @author zhangwei_david * @version $Id: DistributedLockService.java, v 0.1 2015年7月1日 下午9:03:33 zhangwei_david Exp $ */ public interface DistributedLockService { /** * 试图获取分布式锁,如果返回true则表示获取了锁 * * @param callback 回调接口 */ public void tryLock(CallBack callback); /** * 视图获取分布式锁,如果在指定timeout时间后容然未能够获取到锁则返回 * * @param callback * @param timeout */ public void tryLock(CallBack callback, long timeout); /** * 回调处理接口 * * @author zhangwei_david * @version $Id: DistributedLockService.java, v 0.1 2015年7月2日 上午10:59:22 zhangwei_david Exp $ */ public interface CallBack { /** * 获取分布式锁后回调方法 */ public void locked(); /** * 获取分布式锁超时回调方法 */ public void expire(); } }
/** * 分布式锁服务实现类 * @author zhangwei_david * @version $Id: DistributedLockServiceImpl.java, v 0.1 2015年7月1日 下午9:05:48 zhangwei_david Exp $ */ @Component public class DistributedLockServiceImpl implements DistributedLockService { private static final String ROOT = "/zk-demo"; /**锁的临时节点**/ private static final String LOCK = "lock"; /**排它锁节点**/ private static final String EXCLUSIVE_LOCK = ROOT + "/" + LOCK; private int sessionTimeout = 3000; /** * @see com.david.common.distributedLock.DistributedLockService#tryLock(com.david.common.distributedLock.DistributedLockService.CallBack, long) */ public void tryLock(final CallBack callback, long timeout) { try { final long expireTime = timeout > 0 ? System.currentTimeMillis() + timeout : -1; final ZooKeeper zk = getZooKeeper(); //向根节点注册一个子节点变化监听器 List<String> nodes = zk.getChildren(ROOT, new Watcher() { public void process(WatchedEvent event) { // 排它锁已经被释放,则视图获取锁 if (event.getState() == KeeperState.SyncConnected && event.getType() == EventType.NodeChildrenChanged) { doLock(zk, callback, expireTime); } } }); // 没有人获取锁则视图获取锁 if (!nodes.contains(LOCK)) { doLock(zk, callback, expireTime); } } catch (Exception e) { } } /** * * @see com.david.common.distributedLock.DistributedLockService#tryLock(com.david.common.distributedLock.DistributedLockService.CallBack) */ public void tryLock(final CallBack callback) { tryLock(callback, -1); } /** * 具体执行分布式锁,如果拥有分布式锁则执行callback回调,然后释放锁 * * @param zk * @param callback * @param expireTime 过期时间 */ private void doLock(ZooKeeper zk, CallBack callback, long expireTime) { try { if (expireTime > 0 && System.currentTimeMillis() > expireTime) { callback.expire(); return; } String path = zk .create(EXCLUSIVE_LOCK, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println(path); if (path != null) { callback.locked(); zk.delete(EXCLUSIVE_LOCK, -1); } } catch (Exception e) { } finally { try { zk.close(); } catch (InterruptedException e) { } } } /** * 获取ZooKeeper * * @param sessionTimeout * @return * @throws Exception */ private ZooKeeper getZooKeeper() throws Exception { final CountDownLatch latch = new CountDownLatch(1); ZooKeeper zk = new ZooKeeper("localhost:2181", sessionTimeout, new Watcher() { public void process(WatchedEvent event) { if (KeeperState.SyncConnected == event.getState()) { //如果客户端已经建立连接闭锁减一 latch.countDown(); } } }); // 等待连接建立 latch.await(); return zk; } /** * Getter method for property <tt>sessionTimeout</tt>. * * @return property value of sessionTimeout */ public int getSessionTimeout() { return sessionTimeout; } /** * Setter method for property <tt>sessionTimeout</tt>. * * @param sessionTimeout value to be assigned to property sessionTimeout */ public void setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; } }
相关推荐
它隐藏了底层的ZooKeeper操作,使得开发者只需调用几个方法即可实现分布式锁的获取和释放。 此外,Curator还提供了一些附加功能,如锁的公平性(按照创建顺序获取锁)、租约(设置锁的持有时间限制)以及锁竞争的...
zk分布式锁1 在分布式系统中,分布式锁是必不可少的组件之一。分布式锁可以确保在分布式环境中,多个节点之间的并发访问被正确地处理。ZooKeeper是一个广泛使用的分布式锁实现方案,本文将对ZooKeeper分布式锁进行...
本压缩包“zk:redis分布式锁.zip”提供了基于Zookeeper(zk)和Redis两种分布式锁实现的示例和相关资料。 首先,我们来看Zookeeper(zk)的分布式锁。Zookeeper是Apache的一个开源项目,提供了一个高可用的、高性能...
Apache Curator是一个ZooKeeper的客户端库,它提供了更高层次的API来简化ZooKeeper的使用,包括实现分布式锁的配方。 在提供的代码示例中,我们展示了如何使用Apache Curator来实现一个健壮的分布式锁。这个实现...
12.1.9 zk的分布式锁
分布式锁是一种在分布式系统中实现同步访问资源的机制,它允许多个节点在同一时间对共享资源进行操作,而不会导致数据不一致或并发问题。在Java开发中,分布式锁的应用广泛,尤其是在微服务架构中,当服务间的通信...
java面试题Redis分布式锁+zk 分布式锁.md
Redis和Zookeeper是两种常用的分布式协调服务,它们都可以用来实现分布式锁,但具体实现方式和特性有所不同。 **Redis分布式锁** Redis作为内存数据库,具有高性能、低延迟的特点,常被用作实现分布式锁。Redis...
分布式锁是一种在分布式系统中实现同步的技术,它允许多个节点在同一时间访问共享资源。在大型分布式环境中,确保数据的一致性和正确性至关重要,这就是分布式锁发挥作用的地方。Zookeeper,一个由Apache开发的...
在本项目"zk_lock"中,它使用了Apache ZooKeeper(简称ZK)这一强大的分布式协调服务来构建分布式锁。ZooKeeper是一个高可用、高性能的分布式服务框架,能够提供诸如配置管理、命名服务、分布式同步、组服务等基础...
zk实现分布式锁 今天我们介绍通过redis实现分布式锁。实际上这三种和java对比看属于一类。都是属于程序外部锁。 原理剖析 上述三种分布式锁都是通过各自为依据对各个请求进行上锁,解锁从而控制放行还是拒绝。...
Zookeeper是一个分布式服务协调框架,它提供了一种简单且高效的方式来实现分布式锁。 **一、Zookeeper简介** Zookeeper是由Apache开发的开源项目,它提供了一个高可用的分布式协调服务,包括命名服务、配置管理、...
【Zookeeper实现分布式锁】 Zookeeper 是 Apache ...总之,Zookeeper 的分布式锁机制是基于其强大的一致性特性和事件通知能力实现的,它在分布式系统中扮演着至关重要的角色,帮助协调和管理分布式环境下的并发操作。
在提供的代码示例中,我们看到一个名为`DistributedLock`的类,它实现了Java的`Lock`接口。`Lock`接口是Java并发库的一部分,提供了与`synchronized`关键字类似的锁定功能,但提供了更多的灵活性和控制。 首先,`...
**分布式锁的实现**: 1. **锁的创建**:每个客户端在Zookeeper上创建一个临时顺序节点,表示请求锁。 2. **锁的获取**:通过比较节点的顺序号,最小序号的节点获得锁。其他节点监听这个最小序号节点的删除事件,...
本实践教程将指导你如何利用Zookeeper实现分布式锁,以便在分布式环境中保证资源访问的互斥性。 **1. Zookeeper概述** Zookeeper是一个分布式协调服务,它为分布式应用提供了简单而强大的命名服务、配置管理、集群...
DB对于系统来说本身就默认为高可用组件,针对一些低频的业务使用DB实现分布式锁也是一个不错的解决方案,比如控制多机器下定时任务的起调,针对审批回调处理等,本文将给出DB实现分布式锁的一些场景以及解决方案,...
Zookeeper是基于PAXOS算法实现的分布式协调服务,它提供了一种简单、高效且可扩展的方式来管理和维护分布式应用中的配置信息、命名服务、状态同步和分布式锁等。Zookeeper的特点包括原子性操作、顺序一致性、单一...