Java操作Zookeeper原理及过程详解

ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。如下图所示,在 Dubbo架构中 Zookeeper 就担任了注册中心这一角色。

maven依赖

<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.6.0</version>
</dependency>

程序其它依赖:

<!-- Logger(log4j2) -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.11.2</version>
</dependency>
<!-- Log4j 1.x API Bridge -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-1.2-api</artifactId>
  <version>2.11.2</version>
</dependency>
<!-- SLF4J Bridge -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.11.2</version>
</dependency>

<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.6.0</version>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
  </exclusions>
</dependency>

API操作代码:

package com.zhi.test;

import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;

/**
 * Zookeeper操作测试
 *
 * @author 张远志
 * @since 2020年5月3日14:31:28
 *
 */
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ZookeeperTest {
  private final Logger logger = LogManager.getLogger(this.getClass());
  private ZooKeeper zooKeeper;
  private final String path = "/test";

  @BeforeAll
  public void init() throws Exception {
    zooKeeper = new ZooKeeper("192.168.59.131:2181", 60000, new Watcher() {
      public void process(WatchedEvent event) {
        logger.info("事件类型:{},路径:{}", event.getType(), event.getPath());
      }
    });
  }

  /**
   * 添加数据,当路径已经存在时会报错,初始版本号为0。第三个参数是权限控制。 <br>
   * 第四个参数,CreateMode:
   * <li>PERSISTENT:持久化保存
   * <li>PERSISTENT_SEQUENTIAL:持久化保存,并且路径附加一个自动增长的序号
   * <li>EPHEMERAL:临时数据,客户端断开连接时自动删除数据(dubbo就是采用这种机制)
   * <li>EPHEMERAL_SEQUENTIAL:客户端断开连接时自动删除数据,并且路径会附加一个自动增长的序号
   * <li>CONTAINER:
   * <li>PERSISTENT_WITH_TTL:客户端断开连接时自动删除数据,当节点在指定时间没有被修改且没有子目录时,数据会被删除
   * <li>PERSISTENT_SEQUENTIAL_WITH_TTL:客户端断开连接时自动删除数据,路径会附加一个自动增长的序号,且当节点在指定时间没有被修改且没有子目录时,数据会被删除
   */
  @Order(1)
  @Test
  public void create() {
    try {
      String back = zooKeeper.create(path, "这是一个测试".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
      logger.info("添加一条数据成功,实际路径:{}", back);
    } catch (Exception e) {
      logger.error("调用create出错", e);
    }
  }

  /**
   * 判断路径是否存在,不存在时返回null
   */
  @Order(2)
  @Test
  public void exists() {
    try {
      Stat stat = zooKeeper.exists(path, false);
      logger.info("路径为{}的节点{}存在", path, stat == null ? "不" : "");
    } catch (Exception e) {
      logger.error("调用exists出错", e);
    }
  }

  /**
   * 查询数据,路径不存在时会报错
   */
  @Order(3)
  @Test
  public void find() {
    try {
      byte[] bits = zooKeeper.getData(path, false, new Stat()); // 路径不存在时会报错
      String data = new String(bits);
      logger.info("路径{}查询到数据:{}", path, data);
    } catch (Exception e) {
      logger.error("调用getData出错", e);
    }
  }

  /**
   * 获取子目录,结果为空时返回一个长度为0的ArrayList
   */
  @Order(3)
  @Test
  public void children() {
    try {
      List<String> list = zooKeeper.getChildren(path, false);
      logger.info("路径{}的子目录有:{}", path, String.join("、", list.toArray(new String[0])));
    } catch (Exception e) {
      logger.error("调用getChildren出错", e);
    }
  }

  /**
   * 修改数据,路径不存在时会报错,版本号与存储中不一致时也报错
   */
  @Order(4)
  @Test
  public void udpate() {
    try {
      Stat stat = zooKeeper.exists(path, false);
      if (stat != null) {
        stat = zooKeeper.setData(path, "这是一个修改测试".getBytes(), stat.getVersion()); // 版本号为-1时不做版本校验
        logger.info("数据修改成功,原版本号:{},新版本号:{}", stat.getAversion(), stat.getVersion());
      }
    } catch (Exception e) {
      logger.error("调用setData出错", e);
    }
  }

  /**
   * 删除节点,路径不存在时报错,版本号不一致时也会报错
   */
  @Order(5)
  @Test
  public void delete() {
    try {
      zooKeeper.delete(path, -1); // -1表示不做版本校验
      logger.info("根据path删除数据成功");
    } catch (Exception e) {
      logger.error("调用delete出错", e);
    }
  }

  @AfterAll
  public void destory() throws Exception {
    if (zooKeeper != null) {
      zooKeeper.close();
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用JMX监控Zookeeper状态Java API

    一.背景 上一篇通过Java自带的JConsole来获取zookeeper状态.主要有几个不方便的地方,zk集群一般会部署3或者5台,在多个JConsole窗口中切换比较麻烦,各个zk服务及历史数据之间,不能直观比较.一般会做一个WEB管理页面来展示集群状态,设置报警阀值来做报警. 二.JVM平台提供Mbeans 在Java5.0以上版本,有一组API可以让Java应用程序和允许的工具监视和管理Java虚拟机(JVM)和虚拟机所在的本机操作系统.该组API在 java.lang.manageme

  • Java实现ZooKeeper的zNode监控

    上一篇文章已经完成了ZooKeeper的基本搭建和使用的介绍,现在开始用代码说话.参考 https://zookeeper.apache.org/doc/current/javaExample.html ,但对场景和代码都做了简化,只实现基本的Watcher功能. 1   场景设计 目的是体验ZooKeeper的Watcher功能.程序监控ZooKeeper的/watcher节点数据变化,当创建或修改数据时,控制台打印当前的数据内容和版本号:当/watcher被删除时,程序退出. /watche

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

    通过zookeeper实现分布式锁 1.创建zookeeper的client 首先通过CuratorFrameworkFactory创建一个连接zookeeper的连接CuratorFramework client public class CuratorFactoryBean implements FactoryBean<CuratorFramework>, InitializingBean, DisposableBean { private static final Logger LOGG

  • java 中 zookeeper简单使用

    一.zookeeper的基本原理 数据模型,如下: ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode.每个ZNode都可以通过其路径唯一标识,比如上图中第三层的第一个ZNode,它的路径是/app1/c1.在每个ZNode上可存储少量数据(默认是1M, 可以通过配置修改,通常不建议在ZNode上存储大量的数据),这个特性非常有用.另外,每个ZNode上还存储了其Acl信息,这里需要注意,虽说ZNode的树形结构跟Unix文件系统很类似,

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

    使用zookeeper实现的分布式锁 分布式锁,实现了Lock接口 复制代码 代码如下: package com.concurrent; import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.concurrent.CountDownLatch;import java.util.concurrent.TimeU

  • ZooKeeper Java API编程实例分析

    本实例我们用的是java3.4.6版本,实例方便大家学习完后有不明白的可以在留言区讨论. 开发应用程序的ZooKeeper Java绑定主要由两个Java包组成: org.apache.zookeeper org.apache.zookeeper.data org.apache.zookeeper包由ZooKeeper监视的接口定义和ZooKeeper的各种回调处理程序组成. 它定义了ZooKeeper客户端类库的主要类以及许多ZooKeeper事件类型和状态的静态定义. org.apache.

  • windows下zookeeper配置java环境变量的方法

    先找到文件 zookeeper的bin目录下编辑zkEnv.cmd 修改如下图 如果你的系统有多个JAVA_HOME类型的系统变量  则需要在该文件中指定用哪一个,并且还要修改windows的jdk环境变量 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持.如果你想了解更多相关内容请查看下面相关链接

  • Java操作Zookeeper原理及过程详解

    ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管理.Master 选举.分布式锁和分布式队列等功能. Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心. 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据.如

  • 在Java中操作Zookeeper的示例代码详解

    依赖 <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.0</version> </dependency> 连接到zkServer //连接字符串,zkServer的ip.port,如果是集群逗号分隔 String connectStr = "192.

  • java操作mongoDB查询的实例详解

    java操作mongo查询的实例详解 前言: MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型.Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且

  • Java并发编程预防死锁过程详解

    这篇文章主要介绍了Java并发编程预防死锁过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在java并发编程领域已经有技术大咖总结出了发生死锁的条件,只有四个条件都发生时才会出现死锁: 1.互斥,共享资源X和Y只能被一个线程占用 2.占有且等待,线程T1已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X 3.不可抢占,其他线程不能强行抢占线程T1占有的资源 4.循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有

  • JAVA DOM解析XML文件过程详解

    这篇文章主要介绍了JAVA DOM解析XML文件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 import java.io.IOException; import javax.xml.parsers.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.No

  • Java打印流原理及实例详解

    这篇文章主要介绍了Java打印流原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 平时我们在控制台打印输出,是调用print方法和println方法完成的,这两个方法都来自于java.io.PrintStream类,该类能够方便地打印各种数据类型的值,是一种便捷的输岀方式. PrintStream类 PrintStream类,为其他输出流添加了功能,使他们能够方便的打印各种数据值表示格式. PrintStream类的特点: 只负责数

  • java的Builder原理和实现详解

    首先给一个简单的Builder设计模式的例子: 主实现类代码如下: /** * 实体类 包含一个静态内部类 Builder */ public class CompanyClient { public String companyName; // 用final修饰的成员变量表示常量,只能被赋值一次,赋值后值无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量. public String companyAddress; public double companyRegfunds;

  • Java switch关键字原理及用法详解

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • Java泛型继承原理与用法详解

    本文实例讲述了Java泛型继承原理与用法.分享给大家供大家参考,具体如下: 一 点睛 当创建了带泛型声明的接口.父类之后,可以为该接口创建实现类,或从该父类来派生子类,但值得指出的是,当使用这些接口.父类时不能再包含类型形参. 如果使用泛型类时没有传入实际的类型参数,Java编译器可能发出警告:使用了未经检查或不安全的操作--这就是泛型检查的警告. 二 实战--传入实际的类型参数 public class A1 extends Apple<String> { // 正确重写了父类的方法,返回值

  • Java 反射机制原理与用法详解

    本文实例讲述了Java 反射机制原理与用法.分享给大家供大家参考,具体如下: 反射反射,程序员的快乐! 1.什么是反射? Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性.而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是

随机推荐