`
zhangwei_david
  • 浏览: 475564 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ZK实现分布式排它锁

 
阅读更多

   排它锁(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;
    }

}

 

 

6
4
分享到:
评论
5 楼 yjy1304 2016-12-01  
List<String> nodes = zk.getChildren(ROOT, new Watcher(){...})
这个对子节点的变化加了个watcher,若果其他的锁也在这个/zk-demo/下操作子节点也会引起这个watcher的process,是不是会有问题
4 楼 newgo333 2015-07-03  
不错
3 楼 zhangwei_david 2015-07-02  
string2020 写道
分布式锁有啥用?


本质上还是一个锁,它的作用就和JDK的Lock一样;只不过是分布式锁是解决分布式环境下问题
2 楼 string2020 2015-07-02  
楼主,能不能帮忙看看这个和zk有关的问题:
http://www.oschina.net/question/1756518_241782
1 楼 string2020 2015-07-02  
分布式锁有啥用?

相关推荐

    zk使用curator实现分布式锁

    它隐藏了底层的ZooKeeper操作,使得开发者只需调用几个方法即可实现分布式锁的获取和释放。 此外,Curator还提供了一些附加功能,如锁的公平性(按照创建顺序获取锁)、租约(设置锁的持有时间限制)以及锁竞争的...

    zk分布式锁1

    zk分布式锁1 在分布式系统中,分布式锁是必不可少的组件之一。分布式锁可以确保在分布式环境中,多个节点之间的并发访问被正确地处理。ZooKeeper是一个广泛使用的分布式锁实现方案,本文将对ZooKeeper分布式锁进行...

    zk:redis分布式锁.zip

    本压缩包“zk:redis分布式锁.zip”提供了基于Zookeeper(zk)和Redis两种分布式锁实现的示例和相关资料。 首先,我们来看Zookeeper(zk)的分布式锁。Zookeeper是Apache的一个开源项目,提供了一个高可用的、高性能...

    zk实现的分布式锁相关代码

    Apache Curator是一个ZooKeeper的客户端库,它提供了更高层次的API来简化ZooKeeper的使用,包括实现分布式锁的配方。 在提供的代码示例中,我们展示了如何使用Apache Curator来实现一个健壮的分布式锁。这个实现...

    12.1.9 zk的分布式锁.md

    12.1.9 zk的分布式锁

    42_分布式锁是啥?对比下redis和zk两种分布式锁的优劣?.zip

    分布式锁是一种在分布式系统中实现同步访问资源的机制,它允许多个节点在同一时间对共享资源进行操作,而不会导致数据不一致或并发问题。在Java开发中,分布式锁的应用广泛,尤其是在微服务架构中,当服务间的通信...

    java面试题Redis分布式锁+zk 分布式锁.md

    java面试题Redis分布式锁+zk 分布式锁.md

    redis和zookeeper实现分布式锁的区别

    Redis和Zookeeper是两种常用的分布式协调服务,它们都可以用来实现分布式锁,但具体实现方式和特性有所不同。 **Redis分布式锁** Redis作为内存数据库,具有高性能、低延迟的特点,常被用作实现分布式锁。Redis...

    zookeeper分布式锁

    分布式锁是一种在分布式系统中实现同步的技术,它允许多个节点在同一时间访问共享资源。在大型分布式环境中,确保数据的一致性和正确性至关重要,这就是分布式锁发挥作用的地方。Zookeeper,一个由Apache开发的...

    zk_lock:用zk实现的分布式锁

    在本项目"zk_lock"中,它使用了Apache ZooKeeper(简称ZK)这一强大的分布式协调服务来构建分布式锁。ZooKeeper是一个高可用、高性能的分布式服务框架,能够提供诸如配置管理、命名服务、分布式同步、组服务等基础...

    基于redis实现分布式锁的原理与方法

    zk实现分布式锁 今天我们介绍通过redis实现分布式锁。实际上这三种和java对比看属于一类。都是属于程序外部锁。 原理剖析 上述三种分布式锁都是通过各自为依据对各个请求进行上锁,解锁从而控制放行还是拒绝。...

    基于zookeeper实现的分布式读写锁

    Zookeeper是一个分布式服务协调框架,它提供了一种简单且高效的方式来实现分布式锁。 **一、Zookeeper简介** Zookeeper是由Apache开发的开源项目,它提供了一个高可用的分布式协调服务,包括命名服务、配置管理、...

    通过zookeeper实现分布式锁

    【Zookeeper实现分布式锁】 Zookeeper 是 Apache ...总之,Zookeeper 的分布式锁机制是基于其强大的一致性特性和事件通知能力实现的,它在分布式系统中扮演着至关重要的角色,帮助协调和管理分布式环境下的并发操作。

    java使用zookeeper实现的分布式锁示例

    在提供的代码示例中,我们看到一个名为`DistributedLock`的类,它实现了Java的`Lock`接口。`Lock`接口是Java并发库的一部分,提供了与`synchronized`关键字类似的锁定功能,但提供了更多的灵活性和控制。 首先,`...

    基于Zookeeper实现分布式锁实践教程

    本实践教程将指导你如何利用Zookeeper实现分布式锁,以便在分布式环境中保证资源访问的互斥性。 **1. Zookeeper概述** Zookeeper是一个分布式协调服务,它为分布式应用提供了简单而强大的命名服务、配置管理、集群...

    MySQL借助DB实现分布式锁思路详解

    DB对于系统来说本身就默认为高可用组件,针对一些低频的业务使用DB实现分布式锁也是一个不错的解决方案,比如控制多机器下定时任务的起调,针对审批回调处理等,本文将给出DB实现分布式锁的一些场景以及解决方案,...

    基于zookeeper临时顺序节点实现分布式调度

    **分布式锁的实现**: 1. **锁的创建**:每个客户端在Zookeeper上创建一个临时顺序节点,表示请求锁。 2. **锁的获取**:通过比较节点的顺序号,最小序号的节点获得锁。其他节点监听这个最小序号节点的删除事件,...

    ZK分布式一致性原理与实践

    Zookeeper是基于PAXOS算法实现的分布式协调服务,它提供了一种简单、高效且可扩展的方式来管理和维护分布式应用中的配置信息、命名服务、状态同步和分布式锁等。Zookeeper的特点包括原子性操作、顺序一致性、单一...

Global site tag (gtag.js) - Google Analytics