`
MauerSu
  • 浏览: 514922 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Zookeeper(七)分布式锁

 
阅读更多
源:http://blog.csdn.net/java2000_wl/article/details/8694270
评:
获取锁实现思路:

1.     首先创建一个作为锁目录(znode),通常用它来描述锁定的实体,称为:/lock_node

2.     希望获得锁的客户端在锁目录下创建znode,作为锁/lock_node的子节点,并且节点类型为有序临时节点(EPHEMERAL_SEQUENTIAL);

        例如:有两个客户端创建znode,分别为/lock_node/lock-1和/lock_node/lock-2

3.     当前客户端调用getChildren(/lock_node)得到锁目录所有子节点,不设置watch,接着获取小于自己(步骤2创建)的兄弟节点

4.     步骤3中获取小于自己的节点不存在 && 最小节点与步骤2中创建的相同,说明当前客户端顺序号最小,获得锁,结束。

5.     客户端监视(watch)相对自己次小的有序临时节点状态

6.     如果监视的次小节点状态发生变化,则跳转到步骤3,继续后续操作,直到退出锁竞争。

[java] view plain copy
print?

    public synchronized boolean lock() throws KeeperException, InterruptedException { 
           if (isClosed()) { 
               return false; 
           } 
           // 如果锁目录不存在, 创建锁目录   节点类型为永久类型 
           ensurePathExists(dir); 
     
           // 创建锁节点,节点类型EPHEMERAL_SEQUENTIAL  
           // 如果不存在小于自己的节点   并且最小节点 与当前创建的节点相同  获得锁 
           // 未获得成功,对当前次小节点设置watch 
           return (Boolean) retryOperation(zop); 
       } 

创建锁目录
[java] view plain copy
print?

    protected void ensurePathExists(String path) { 
        ensureExists(path, null, acl, CreateMode.PERSISTENT); 
    } 

[java] view plain copy
print?

    protected void ensureExists(final String path, final byte[] data, 
            final List<ACL> acl, final CreateMode flags) { 
        try { 
            retryOperation(new ZooKeeperOperation() { 
                public boolean execute() throws KeeperException, InterruptedException { 
                    // 创建锁目录 
                    Stat stat = zookeeper.exists(path, false); 
                    // 节点如果存在  直接返回 
                    if (stat != null) { 
                        return true; 
                    } 
                    // 创建节点 
                    // data为null 
                    // flags为持久化节点 
                    zookeeper.create(path, data, acl, flags); 
                    return true; 
                } 
            }); 
        } catch (KeeperException e) { 
            LOG.warn("Caught: " + e, e); 
        } catch (InterruptedException e) { 
            LOG.warn("Caught: " + e, e); 
        } 
    } 


创建锁节点,获得锁目录下的所有节点, 如果为最小节点 获得锁成功

[java] view plain copy
print?

        /**
         * the command that is run and retried for actually 
         * obtaining the lock
         * @return if the command was successful or not
         */ 
        public boolean execute() throws KeeperException, InterruptedException { 
            do { 
                if (id == null) { 
                    long sessionId = zookeeper.getSessionId(); 
                    String prefix = "x-" + sessionId + "-"; 
                    // lets try look up the current ID if we failed  
                    // in the middle of creating the znode 
                    findPrefixInChildren(prefix, zookeeper, dir); 
                    idName = new ZNodeName(id); 
                } 
                if (id != null) { 
                    List<String> names = zookeeper.getChildren(dir, false); 
                    if (names.isEmpty()) { 
                        LOG.warn("No children in: " + dir + " when we've just " + 
                        "created one! Lets recreate it..."); 
                        // lets force the recreation of the id 
                        id = null; 
                    } else { 
                        // lets sort them explicitly (though they do seem to come back in order ususally 
                        SortedSet<ZNodeName> sortedNames = new TreeSet<ZNodeName>(); 
                        for (String name : names) { 
                            sortedNames.add(new ZNodeName(dir + "/" + name)); 
                        } 
                        // 获得最小节点 
                        ownerId = sortedNames.first().getName(); 
                        // lock_1, lock_2, lock_3  传入参数lock_2  返回lock_1 
                        SortedSet<ZNodeName> lessThanMe = sortedNames.headSet(idName); 
                        if (!lessThanMe.isEmpty()) { 
                            ZNodeName lastChildName = lessThanMe.last(); 
                            lastChildId = lastChildName.getName(); 
                            if (LOG.isDebugEnabled()) { 
                                LOG.debug("watching less than me node: " + lastChildId); 
                            } 
                            // 次小节点设置watch  
                            Stat stat = zookeeper.exists(lastChildId, new LockWatcher()); 
                            if (stat != null) { 
                                return Boolean.FALSE; 
                            } else { 
                                LOG.warn("Could not find the" + 
                                        " stats for less than me: " + lastChildName.getName()); 
                            } 
                        } else { 
                            // 锁目录下的最小节点  与当前客户端创建相同 
                            if (isOwner()) { 
                                if (callback != null) { 
                                    callback.lockAcquired(); 
                                } 
                                // 获得锁 
                                return Boolean.TRUE; 
                            } 
                        } 
                    } 
                } 
            } 
            while (id == null); 
            return Boolean.FALSE; 
        } 
    }; 


[java] view plain copy
print?

    private void findPrefixInChildren(String prefix, ZooKeeper zookeeper, String dir)  
                throws KeeperException, InterruptedException { 
                // 获取锁目录下的所有子节点 
                List<String> names = zookeeper.getChildren(dir, false); 
                for (String name : names) { 
                    //x-sessionId- 
                    if (name.startsWith(prefix)) { 
                        id = name; 
                        if (LOG.isDebugEnabled()) { 
                            LOG.debug("Found id created last time: " + id); 
                        } 
                        break; 
                    } 
                } 
                // 当前锁目录下   没有与当前会话对应的子节点    创建子节点  节点类型为临时顺序节点 
                if (id == null) { 
                    // dir/x-sessionId-i 
                    id = zookeeper.create(dir + "/" + prefix, data,  
                            getAcl(), EPHEMERAL_SEQUENTIAL); 
     
                    if (LOG.isDebugEnabled()) { 
                        LOG.debug("Created id: " + id); 
                    } 
                } 


释放锁:

释放锁非常简单,删除步骤1中创建的有序临时节点。另外,如果客户端进程死亡或连接失效,对应的节点也会被删除。

[java] view plain copy
print?

    public synchronized void unlock() throws RuntimeException { 
            
           if (!isClosed() && id != null) { 
               // we don't need to retry this operation in the case of failure 
               // as ZK will remove ephemeral files and we don't wanna hang 
               // this process when closing if we cannot reconnect to ZK 
               try { 
                    
                   ZooKeeperOperation zopdel = new ZooKeeperOperation() { 
                       public boolean execute() throws KeeperException, 
                           InterruptedException { 
                        // 删除节点  忽略版本 
                           zookeeper.delete(id, -1);    
                           return Boolean.TRUE; 
                       } 
                   }; 
                   zopdel.execute(); 
               } catch (InterruptedException e) { 
                   LOG.warn("Caught: " + e, e); 
                   //set that we have been interrupted. 
                  Thread.currentThread().interrupt(); 
               } catch (KeeperException.NoNodeException e) { 
                   // do nothing 
               } catch (KeeperException e) { 
                   LOG.warn("Caught: " + e, e); 
                   throw (RuntimeException) new RuntimeException(e.getMessage()). 
                       initCause(e); 
               } 
               finally { 
                   if (callback != null) { 
                       callback.lockReleased(); 
                   } 
                   id = null; 
               } 
           } 
       } 
分享到:
评论

相关推荐

    基于zookeeper的分布式锁简单实现

    这时,Zookeeper,一个高可用的分布式协调服务,常被用来实现分布式锁。 Zookeeper由Apache基金会开发,它提供了一种可靠的分布式一致性服务,包括命名服务、配置管理、集群同步、领导者选举等功能。Zookeeper基于...

    使用ZooKeeper实现分布式锁

    在处理订单生成的场景中,我们可以这样应用ZooKeeper分布式锁: 1. 当用户发起订单请求时,服务端会尝试在ZooKeeper上创建一个临时顺序节点。 2. 如果创建成功,服务端会检查当前最小序号的节点是否是自己创建的。...

    基于zookeeper的分布式锁实现demo

    **Zookeeper分布式锁的关键特性包括:** 1. **顺序一致性:** Zookeeper中的节点被创建顺序是全局唯一的,这有助于实现锁的唯一性。 2. **原子性:** 创建和删除节点的操作在Zookeeper中都是原子性的,这保证了...

    zookeeper做分布式锁

    分布式锁是解决多节点系统中同步问题的一种常见技术,ZooKeeper,由Apache基金会开发的分布式协调服务,常被用于实现高效可靠的分布式锁。本文将深入探讨如何利用ZooKeeper来构建分布式锁,并讨论其背后的关键概念和...

    基于zookeeper实现分布式锁

    zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是集群的管理者。提供了文件系统和通知机制。...在开发项目的过程中,很多大型项目都是分布式部署的,那么我们现在使用zookeeper实现一个分布式锁。

    ZooKeeper-分布式过程协同技术详解 和从Paxos到Zookeeper

    书中还详细介绍了ZooKeeper的应用场景,如命名服务、配置管理、集群管理、分布式锁等。在命名服务中,ZooKeeper可以作为一个全局的名字注册表,使得分布式系统中的组件可以找到彼此。配置管理则允许系统动态更新配置...

    使用zookeeper实现分布式共享锁

    Zookeeper的分布式锁主要基于两种数据结构:临时节点(ephemeral nodes)和顺序节点(sequential nodes)。 首先,临时节点是当客户端断开连接时会被自动删除的节点。这种特性使得Zookeeper可以检测到节点的存活...

    从Paxos到Zookeeper分布式一致性原理与实践 + ZooKeeper-分布式过程协同技术详解 pdf

    《从Paxos到Zookeeper分布式一致性原理与实践》与《ZooKeeper-分布式过程协同技术详解》这两本书深入探讨了分布式系统中的一个重要概念——一致性,以及如何通过ZooKeeper这一工具来实现高效的分布式协同。...

    zookeeper实现分布式锁

    在程序开发过程中不得不考虑的就是并发问题。在java中对于同一个jvm而言,jdk已经提供了lock和同步等。但是在分布式情况下,往往存在多个进程对一些资源产生竞争...分布式锁顾明思议就是可以满足分布式情况下的并发锁。

    通过zookeeper实现分布式锁

    【Zookeeper实现分布式锁】 Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个高性能的分布式协调服务。它提供了一种可靠的方式来管理分布式系统中的配置信息、命名服务、集群管理和同步服务。Zookeeper 的...

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

    **Zookeeper分布式锁** Zookeeper是一个高可用的分布式协调服务,它维护了一致的命名空间和分布式事件通知。Zookeeper中的分布式锁通常通过创建临时节点(ephemeral nodes)来实现。当客户端创建一个临时节点并持有...

    吊打面试官之基于zookeeper实现分布式锁源码

    本主题将深入探讨如何利用ZooKeeper实现分布式锁,并结合SpringCloud生态进行应用。ZooKeeper是一个分布式协调服务,而分布式锁是它的一个重要应用场景。 **ZooKeeper的特性与角色** 1. **强一致性**:ZooKeeper...

    Zookeeper实现分布式锁

    4. **zkLockTest**:这个文件很可能是实现Zookeeper分布式锁的测试代码,可能包含客户端的连接、锁的获取和释放、异常处理等逻辑。通过对这个测试代码的分析和运行,我们可以深入理解Zookeeper分布式锁的工作机制。 ...

    《Paxos到Zookeeper——分布式一致性原理与实践》高清完整版

    5. 实战应用:通过具体案例展示如何在实际项目中运用Zookeeper解决分布式协调问题,例如配置管理、服务发现、分布式锁等。 6. 高可用与故障恢复:探讨Zookeeper的容错机制,如何保证服务的高可用性和数据的一致性。 ...

    zookeeper分布式锁实例源码

    在这个场景下,我们将关注ZooKeeper如何实现分布式锁,特别是不可重入锁、可重入锁以及可重入读写锁的概念与实践。 首先,我们要理解什么是分布式锁。在多节点并发访问共享资源时,分布式锁能确保同一时刻只有一个...

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

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

    浅谈Java(SpringBoot)基于zookeeper的分布式锁实现

    Java(SpringBoot)基于zookeeper的分布式锁实现 本文主要介绍了Java(SpringBoot)基于zookeeper的分布式锁实现,通过示例代码详细介绍了分布式锁的实现过程,对大家的学习或者工作具有一定的参考学习价值。 分布式锁...

    zookeeper分布式锁实现和客户端简单实现

    Zookeeper提供了一种类似于文件系统的数据模型,可以用于命名服务、配置管理、集群管理、分布式锁等场景。它具有强一致性、高可用性和高性能的特点,是实现分布式锁的理想选择。 **Zookeeper的分布式锁实现原理** ...

    zookeeper的分布式全局锁纯代码解决方案

    在这个"zookeeper的分布式全局锁纯代码解决方案"中,我们将探讨如何利用Zookeeper来构建一套易于理解和扩展的分布式锁。 首先,Zookeeper的特性使其成为实现分布式锁的理想选择。Zookeeper提供了原子性的读写操作、...

    ZooKeeper-分布式过程协同技术详解-最新版

    4. **分布式锁**:提供分布式环境下的互斥访问控制,防止多个节点同时对同一资源进行操作。 5. **队列服务**:实现先进先出(FIFO)的队列,用于任务调度或消息传递。 Zookeeper的设计遵循了CAP理论中的CP原则,即...

Global site tag (gtag.js) - Google Analytics