zookeeper-节点操作和分布式锁实现

zookeeper节点操作
  1. zookeeper节点操作
    • 节点创建,删除,遍历
    • 节点数据读写
  2. 节点类型

节点类型

持久节点   PERSISTENT
持久顺序节点 PERSISTENT_SEQUENTIAL
临时节点  EPHEMERAL
临时顺序节点    EPHEMERAL_SEQUENTIAL

节点操作见实例代码

public class ConnectionWatcher implements Watcher {

    private static final int SESSION_TIMEOUT = 5000;

    public ZooKeeper zk;

    private CountDownLatch connectedSignal = new CountDownLatch(1);

    public void connect(String host) throws IOException {
        try {
            zk=new ZooKeeper(host,SESSION_TIMEOUT,this);
            connectedSignal.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void closeZk() throws InterruptedException {
        zk.close();
    }
    @Override
    public void process(WatchedEvent watchedEvent) {
        if(watchedEvent.getState()==Watcher.Event.KeeperState.SyncConnected)
            connectedSignal.countDown();
        System.out.println("监听到事件!");
    }
}
public class ZookeeperTest extends ConnectionWatcher{

    @Override

    public  void connect(String host) throws IOException {
        super.connect(host);
    }
    @Override
    public void closeZk() throws InterruptedException{
        super.closeZk();
    }
    @Override
    public void process(WatchedEvent watchedEvent) {
        super.process(watchedEvent);
        System.out.println("数据已修改");
    }



    public static void main(String[] args) throws Exception{
        ZookeeperTest zookeeperTest = new ZookeeperTest();
        zookeeperTest.connect("192.168.31.201:2181");
        String fatherNode="testZookeeper";
//        zookeeperTest.createZNode("testZookeeper");

//        zookeeperTest.join(fatherNode, "twoPath");
//        Thread.sleep(30000);
//        zookeeperTest.listGroup(fatherNode);
        String data="this is zookeeper data";


        zookeeperTest.wrideDataToNode(fatherNode,data,-1);
        zookeeperTest.getDataFromNode(fatherNode);
//        zookeeperTest.deleteNode(fatherNode);
        Thread.currentThread().suspend();
    }

    /**
     * 在给定的节点下创建临时节点
     * @param groupName
     * @param numberName
     * @throws Exception
     */
    public void join(String groupName,String numberName)throws Exception{
        String path="/"+groupName+"/"+numberName;
        String createPath=zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        System.out.println(createPath);
    }
    /**
     * 获取 指定节点下的子节点
     * @param groupName
     * @throws KeeperException
     * @throws InterruptedException
     */
    public  void listGroup(String groupName) throws KeeperException, InterruptedException {
        String patchGroup="/"+groupName;
        List<String>listNode=zk.getChildren(patchGroup,false);
        if(listNode.isEmpty()){
            System.out.print("this is no child Node");
        }else{
            System.out.print(listNode.toString());
        }
    }

    /**
     * 删除指定 节点 以及子节点
     * 不支持递归删除,只能从子节点往上删除
     * @param groupName
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void deleteNode(String groupName) throws KeeperException, InterruptedException {
        String patchGroup="/"+groupName;
        List<String> childrenNodes=zk.getChildren(patchGroup,false);
        for(String node:childrenNodes){
            zk.delete(patchGroup+"/"+node,-1 );
        }
        zk.delete(patchGroup,-1);
        System.out.println("delete OK");
    }

    /**
     * 创建指定永久节点
     * @param zNode
     * @throws Exception
     */
    public void createZNode(String zNode) throws Exception{
        String path="/"+zNode;
        String createPath = zk.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(createPath);
    }

    /**
     *  version -1  基于数据最新版本进行更新操作
     * @param zNode
     * @param data
     * @param version
     */
    public void wrideDataToNode(String zNode,String data,int version){

        String path="/"+zNode;
        try {
            zk.setData(path,data.getBytes(),version);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("向节点"+path+"写入成功!");
    }

    public void getDataFromNode(String zNode){
        String path="/"+zNode;
        try {
           System.out.println( new String(zk.getData(path,true,null)));
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
  1. Curator zookeeper 实现分布式锁

    • 原理
    • 临时顺序节点
    • 实例代码
    • 关于版本问题
Curator zookeeper 实现分布式锁

原理

每个JVM使用同一个客户端实例,客户端实例对某个方法加锁的时候,
zookeeper对应节点下生成一个唯一的临时顺序节点,如果是序号最小的,则获得锁,释放锁的时候删除节点。

怠机的时候临时节点会自动删除,不会有死锁。

临时顺序节点

如图是调试过程中 在zookeeper中生成用于判断锁的临时顺序节点

mark

实例代码

 private static final String ZK_ADDRESS = "192.168.31.201:2181";//地址
    private static final String ZK_LOCK_PATH = "/zktest";//path
    static SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static void main(String[] args) throws Exception {


//      CuratorFramework client= CuratorFrameworkFactory.newClient(ZK_ADDRESS,new RetryNTimes(10,5000));
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client= CuratorFrameworkFactory.newClient(ZK_ADDRESS,3000, 1000, retryPolicy);
        client.start();

         InterProcessMutex lock =new InterProcessMutex(client,ZK_LOCK_PATH);

        Thread thread1 =new Thread(()->{
            doWithLock(client,lock);
        },"t1");
        Thread thread2 =new Thread(()->{
            doWithLock(client,lock);
        },"t2");
        Thread thread3 =new Thread(()->{
            doWithLock(client,lock);
        },"t3");
        thread1.start();
        thread2.start();
        thread3.start();
    }

    private static void doWithLock(CuratorFramework client, InterProcessMutex lock) {
        Boolean isLock=false;

        System.out.println("进入线程"+Thread.currentThread().getName()+":"+time.format(new Date()));

        try {
            if(lock.acquire(1, TimeUnit.SECONDS)){//1秒的时间等待锁
                isLock=true;
                System.out.println(Thread.currentThread().getName()+"获取锁成功!执行加锁任务"+time.format(new Date()));
                Thread.sleep(2000L);
            }else{
                System.out.println("获取锁超时!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName()+"释放锁!"+time.format(new Date()));
            try {
                if(isLock){
                    lock.release();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
pom.xml


  <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
      <dependency>
          <groupId>org.apache.curator</groupId>
          <artifactId>curator-framework</artifactId>
          <version>2.12.0</version>
      </dependency>


      <dependency>
          <groupId>org.apache.curator</groupId>
          <artifactId>curator-recipes</artifactId>
          <version>2.12.0</version>
      </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-client -->
    <dependency>
      <groupId>org.apache.curator</groupId>
      <artifactId>curator-client</artifactId>
        <version>2.12.0</version>
    </dependency>

关于版本问题

Curator 2.x.x兼容Zookeeper的3.4.x3.5.x。
而Curator 3.x.x只兼容Zookeeper 3.5.x,并且提供了一些诸如动态重新配置、watch删除等新特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值