zookeeper使用curator框架调用实例

zookeeper的原理分析参考链接:https://blog.csdn.net/gelong_bokewang/article/details/89208234

zookeeper的安装步骤参考链接:https://blog.csdn.net/gelong_bokewang/article/details/89157375

本文是使用CUrator框架来调用zookeeper客户端,因为zookeeper客户端更加偏向于底层一些,我们如果自己封装的话不如使用现有的框架来的方便。

 

这里我们需要引入的jar包:


    
      org.apache.zookeeper
      zookeeper
      3.4.14
    

    
    
      org.apache.curator
      curator-recipes
      4.1.0
    

    
    
      org.apache.curator
      curator-client
      4.1.0
    

 

锁原理:

1、客户端连接zookeeper,并在/lock下创建临时的且有序的子节点,第一个客户端对应的子节点为/lock/lock-0000000000,第二个为/lock/lock-0000000001,以此类推。

2、想要获取锁的客户端在锁的根节点下面创建znode,作为/mylock的子节点,节点的类型要选择CreateMode.PERSISTENT_SEQUENTIAL,,假设目前同时有3个客户端想要获得锁,那么/mylock下的目录应该是这个样子的。

xxx-lock-0000000001,xxx-lock-0000000002,xxx-lock-0000000003

xxx为uuid , 0000000001,0000000002,0000000003 是zook服务端自动生成的自增数字。

3、当前客户端通过getChildren(/mylock)获取所有子节点列表并根据自增数字排序,然后判断一下自己创建的节点的顺序是不是在列表当中最小的,如果是 那么获取到锁,如果不是,那么获取自己的前一个节点,并设置监听这个节点的变化,当节点变化时重新执行步骤3 直到自己是编号最小的一个为止。

举例:假设当前客户端创建的节点是0000000002,因为它的编号不是最小的,所以获取不到锁,那么它就找到它前面的一个节点0000000001 并对它设置监听。

4、释放锁,当前获得锁的客户端在操作完成后删除自己创建的节点,这样会激发zook的事件给其它客户端知道,这样其它客户端会重新执行(步骤3)。

举例:加入客户端0000000001获取到锁,然后客户端0000000002加入进来获取锁,发现自己不是编号最小的,那么它会监听它前面节点的事件(0000000001的事件)然后执行步骤(3),当客户端0000000001操作完成后删除自己的节点,这时zook服务端会发送事件,这时客户端0000000002会接收到该事件,然后重复步骤3直到获取到锁)

 

下面是代码示例:

工具类:这里Curator是一个重量级对象,最好唯一,统一初始化。

package src.main.javas.com.gl.zookeeper;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
 * @ ZookeeperUtil
 * 因为Curator客户端是重量级对象,只需要初始化一次
 */
public class ZookeeperUtil {

    /**
     * 超时重试的时间
     */
    private static final Integer baseSleepTimeMs = 1000;

    /**
     * 超时重试的次数
     */
    private static final Integer maxRetries = 3;

    /**
     * zookeeper服务器的地址端口
     */
    private static final String connectString = "192.168.80.112:2181,192.168.80.112:2182,192.168.80.112:2183";

    /**
     * 操作失败重试机制
     */
    private RetryPolicy retryPolicy;

    /**
     * Curator客户端
     */
    private CuratorFramework curatorFramework;

    /**
     * 初始化
     */
    public ZookeeperUtil() {
        retryPolicy = new ExponentialBackoffRetry(baseSleepTimeMs, maxRetries);
        curatorFramework = CuratorFrameworkFactory.newClient(connectString,retryPolicy);
        curatorFramework.start();
    }

    public CuratorFramework getCuratorFramework() {
        return curatorFramework;
    }

    public void close() {
        curatorFramework.close();
    }
}

实现代码:

package src.main.javas.com.gl.zookeeper;

import org.apache.curator.framework.recipes.locks.InterProcessMutex;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ZookeeperDemo1 {

    public static void main(String[] args) throws Exception {

        ZookeeperUtil zookeeperUtil = new ZookeeperUtil();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,10000, TimeUnit.SECONDS,
                new ArrayBlockingQueue(1),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        test(zookeeperUtil, threadPoolExecutor);
        //关闭
        //zookeeperUtil.close();
    }

    public static void test(ZookeeperUtil zookeeperUtil, ThreadPoolExecutor threadPoolExecutor) {
        threadPoolExecutor.execute(() ->{
            try {
                /**
                 * 这个类是线程安全的,一个JVM创建一个就好
                 * mylock 为锁的根目录,我们可以针对不同的业务创建不同的根目录
                 */
                final InterProcessMutex lock = new InterProcessMutex(zookeeperUtil.getCuratorFramework(), "/mylock");
                try {
                    //阻塞方法,获取不到锁线程会挂起。
                    lock.acquire();
                    System.out.println("已经获取到锁1");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                finally{
                    //释放锁,必须要放到finally里面,已确保上面方法出现异常时也能够释放锁。
                    Thread.sleep(3000);
                    lock.release();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                threadPoolExecutor.shutdown();
            }
        });

        threadPoolExecutor.execute(() -> {
            try {
                /**
                 * 这个类是线程安全的,一个JVM创建一个就好
                 * mylock 为锁的根目录,我们可以针对不同的业务创建不同的根目录
                 */
                final InterProcessMutex lock = new InterProcessMutex(zookeeperUtil.getCuratorFramework(), "/mylock");
                try {
                    //阻塞方法,获取不到锁线程会挂起。
                    lock.acquire();
                    System.out.println("已经获取到锁2");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                finally{
                    Thread.sleep(5000);
                    //释放锁,必须要放到finally里面,已确保上面方法出现异常时也能够释放锁。
                    lock.release();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                threadPoolExecutor.shutdown();
            }
        });

        threadPoolExecutor.execute(() -> {
            try {
                /**
                 * 这个类是线程安全的,一个JVM创建一个就好
                 * mylock 为锁的根目录,我们可以针对不同的业务创建不同的根目录
                 */
                final InterProcessMutex lock = new InterProcessMutex(zookeeperUtil.getCuratorFramework(), "/mylock");
                try {
                    //阻塞方法,获取不到锁线程会挂起。
                    lock.acquire();
                    System.out.println("已经获取到锁3");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                finally{
                    Thread.sleep(8000);
                    //释放锁,必须要放到finally里面,已确保上面方法出现异常时也能够释放锁。
                    lock.release();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                threadPoolExecutor.shutdown();
            }
        });
    }
}

 

运行上述的代码时候我们可以在zookeeper服务器上进行查询可以看到如下结果:


zookeeper使用curator框架调用实例_第1张图片

 

这样的输出我们明显的能看明白zookeeper分布式锁的原理,他是一个先进先出的机制,而且这里我们明显能够看到的它获取锁的方式。

你可能感兴趣的:(zookeeper,java学习)