美文网首页
zookeeper实现分布式锁

zookeeper实现分布式锁

作者: 守住阳光 | 来源:发表于2018-10-13 11:27 被阅读0次

            分布式锁主要解决多个进程访问同一资源时的资源竞争问题。主要有三种解决方案,基于数据库实现分布式锁,基于缓存实现分布式锁和基于zookeeper实现分布式锁。

    一、三种实现方案介绍

    1、基于数据库实现分布式锁

            基于数据库实现分布式锁实现起来比较简单,但是其有如下缺点:

            (1)性能较差,容易出现单点故障,此由数据库连接池的连接数决定的;

            (2)锁没有失效时间,容易死锁,经常出现的情况是线程死了,数据库记录没有删除,导致出现死锁;

            (3)非阻塞式。

    2、基于缓存实现分布式锁

            基于缓存实现分布式锁原理和基于数据库类似,其性能和并发量相较于数据库实现要大大提升,但是也会有如下缺点:

            (1)需要为锁设置失效时间,但是失效时间无法准确设定。

    3、基于zookeeper实现分布式锁

            基于zookeeper相较于前面两种方案,其性能和可靠性都有所提升,也是最长采用的方案,其特点如下:

            (1)实现简单;

            (2)可靠性好;

            (3)性能好。

    二、zookeeper简介

            zookeeper是一个分布式的、开放源代码的分布式应用程序协调服务,是Hadoop和Hbase的重要组件。在zk中zNode是一个跟Unix或者Windows文件系统路径相似的节点,可以往这个节点存储或者获取数据。

            通过客户端可以对zNode进行增删改查操作,还可以注册watcher监控zNode的变化。zNode跟文件系统一样,名称不可重复。

            zk的节点类型包括:持久节点,持久顺序节点,临时节点,临时顺序节点。临时节点跟会话有关,连接断掉,节点会被自动删除。

    三、基于zookeeper实现分布式锁的代码示例

    1、定义Lock接口

    public interface Lock {

            public void lock();

            public void unLock();

    }

    2、Lock抽象类(模板模式)     

    public abstract class AbstractLock implements Lock{ 

             protected static String host = "127.0.0.1";

             protected static int port = 2181; 

             protected static String path = "/lock"; 

             protected static ZkClient zkClient = new ZkClient(host, port);

             @Override 

             public void lock() { 

                 if(tryLock()){

                        System.out.println("获取锁成功!!!");              

                 }else{                  

                         //如果尝试获取锁失败,则等待获取锁                 

                         waitForLock();                  

                         lock();              

                 } 

            }

             protected abstract boolean tryLock(); 

             protected abstract void waitForLock(); 

     } 

    3、锁的具体实现类

    public class ZookeeperLock extends AbstractLock{

            private CountDownLatch cdl =null;

            /**

            * 解锁即删除临时节点

            */

            @Override

            public void unLock() {

                    zkClient.delete(path);

            }

            /**

            * 如果创建临时节点成表示获取锁成功

            */

            @Override

            protected boolean tryLock() {

                try{

                    zkClient.createEphemeral(path);

                    return true;

                }catch(Exception e){

                    return false ;

                }

            }

            @Override

            protected void waitForLock() {

                    IZkDataListener listener = new IZkDataListener(){

                            @Override

                            public void handleDataChange(String dataPath, Object data) throws Exception {

                            }

                            @Override

                            public void handleDataDeleted(String dataPath) throws Exception {

                                    //监听临时节点删除事件

                                    if(cdl!=null){

                                        cdl.countDown();

                                    }

                            }

                };

                //订阅节点改变事件

               zkClient.subscribeDataChanges(path, listener);

               if(zkClient.exists(path)){

                    //线程在此阻塞,直到临时节点删除事件触发

                    cdl = new CountDownLatch(1);

                    try {

                             cdl.await();

                    } catch (InterruptedException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                    }

               }

                zkClient.unsubscribeDataChanges(path, listener);

            }

    }

    相关文章

      网友评论

          本文标题:zookeeper实现分布式锁

          本文链接:https://www.haomeiwen.com/subject/jxcoaftx.html