• zookeeper基本使用


    zookeeper基本使用

    1. zookeeper简介

    Zookeeper是一个分布式协调服务, 是为用户的分布式应用程序提供协调服务

    • Zookeeper是为别的分布式程序服务的
    • Zookeeper本身就是一个分布式程序(只要有半数以上节点存活,zk就能正常服务)
    • Zookeeper所提供的服务涵盖:主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务……
    • 虽然说可以提供各种服务,但是zookeeper在底层其实只提供了两个功能:
      管理(存储,读取)用户程序提交的数据;
      并为用户程序提供数据节点监听服务;

    2. zookeeper安装配置及集群搭建

    2.1 下载 --> 官网
    2.2 上传到linux后,解压
    2.3 进入zookeeper目录,其根目录下几个目录如下
    bin目录: 一些操作zookeeper的指令

    zkServer.sh [start | stop | status | restart ]

    conf目录: 配置文件

    # 将conf目录下的 zoo_sample.cfg 复制一份为 zoo.cfg , zookeeper服务器启动默认加载zoo.cfg
    cp  ./conf/zoo_sample.cfg  ./zoo.cfg
    
    # 修改zoo.cfg中的配置, 修改内容如下
    dataDir=/root/work/zookeeper/data     #  配置数据目录,创建一个data目录,将其路径填入即可
    dataLogDir=/root/work/zookeeper/log   # 同理(可以不配置此项)
    # 配置集群节点,server.x中 x 为节点id, slave1 为节点服务器主机名,或者ip地址
    # 节点id配置, 在data目录下创建文件名为myid的文件,在文件中直接写入id即可,例如 slave1的myid文件中写   1  
    server.1=slave1:2888:3888 (主机名, 心跳端口、数据端口)
    server.2=slave2:2888:3888
    server.3=slave3:2888:3888
    

    zookeeper集群机制为半数机制, 即集群中半数以上机器存活集群才可用。

    启动集群,把每个节点的zookeeper
    zkServer.sh start
    查看状态, 主从信息
    zkServer.sh status

    3. zookeeper 结构命令

    3.1 zookeeper 特性

    1、Zookeeper:一个leader,多个follower组成的集群
    2、全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的
    3、分布式读写,更新请求转发,由leader实施
    4、更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行
    5、数据更新原子性,一次数据更新要么成功,要么失败
    6、实时性,在一定时间范围内,client能读到最新数据

    3.2 zookeeper 数据结构

    1、层次化的目录结构,命名符合常规文件系统规范(见下图)
    znode
    2、每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
    3、节点Znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)
    4、客户端应用可以在节点上设置监视器

    3.3 zookeeper节点类型

    1、Znode有两种类型:

    短暂(ephemeral)(断开连接自己删除)
    持久(persistent)(断开连接不删除)

    2、Znode有四种形式的目录节点(默认是persistent )

    PERSISTENT
    PERSISTENT_SEQUENTIAL(持久序列,例如 create -s /test 生成znode为 /test0000000001 )
    EPHEMERAL
    EPHEMERAL_SEQUENTIAL

    3、创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
    4、在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序

    3.4 znode节点元数据stat,例子

    cZxid = 0xb00000003    内部数据更新时的事务控制的编号,创建一个数据时,内部就会有一个事务编号
    ctime = Tue Feb 13 08:32:40 CST 2018  创建时间
    mZxid = 0xb00000005  修改事务的编号
    mtime = Tue Feb 13 08:34:47 CST 2018 修改时间
    pZxid = 0xb00000003 持久化事务编号
    cversion = 0 创建版本号
    dataVersion = 1 数据版本号
    aclVersion = 0  权限版本
    ephemeralOwner = 0x0
    dataLength = 5 数据长度
    numChildren = 0  子节点数
    

    3.5zookeeper 命令行操作

    运行 zkCli.sh –server ip:port 进入命令行工具

    [zk: localhost:2181(CONNECTED) 0] help    # help 指令查看帮助
    ZooKeeper -server host:port cmd args  
    	connect host:port    # 连接到zookeeper集群中其他节点
    	get path [watch]     #  获取 path 的数据, wath (只监听一次)选项,监听 znode 数据变化
    	ls path [watch]        #  获取 path 下的 znode 列表
    	set path data [version]  # 修改 path 下znode的data
     	rmr path                 #  递归删除 path 节点及其子节点
    	delquota [-n|-b] path
    	quit                       # 退出 zookeeper 客户端
    	printwatches on|off
    	create [-s] [-e] path data acl  # 创建节点, -s 设置顺序标识  -e 创建节点为短暂类型   acl 权限
    	stat path [watch]    # 查看 path 的元数据
    	close 
    	ls2 path [watch]
    	history 
    	listquota path
    	setAcl path acl
    	getAcl path
    	sync path
    	redo cmdno
    	addauth scheme auth
    	delete path [version]   # 删除path节点,只能用于删除叶子节点
    	setquota -n|-b val path
    

    4. java操作zookeeper客户端

    4.1 搭建环境

    • 方法一: 建立一个maven项目,在pom.xml中添加zookeeper客户端依赖
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.10</version>
    </dependency>
    
    • 方法二: 建立一个普通的java项目,创建一个lib目录, 将zookeeper解压后的根目录下的 zookeeper-3.4.10.jar 和 根目录下的lib目录下的jar包一起拷贝到java项目的lib目录下,并将他们导入到项目环境中。

    4.2 基本使用

    org.apache.zookeeper.Zookeeper是客户端入口主类,负责建立与server的会话
    它提供了表 1 所示几类主要方法 :

    功能 描述
    create 在本地目录树中创建一个节点
    delete 删除一个节点
    exists 测试本地是否存在目标节点
    get/set data 从目标节点上读取 / 写数据
    get/set ACL 获取 / 设置目标节点访问控制列表信息
    get children 检索一个子节点上的列表
    sync 等待要被传送的数据

    4.2.1 基本操作,增删改查

    package com.lunarku.bigdata.zk;
    
    import java.util.List;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    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.Before;
    import org.junit.Test;
    
    /**
     * java代码操作zookeeper测试
     */
    public class SimpleZkClient {
    	
    	// zookeeper集群服务器ip端口
    	private static final String CONNECT_STRING=
    			"192.168.25.141:2181,192.168.25.142:2181,192.168.25.143:2181";
    	private static final int SESSION_TIMEOUT = 2000;
    	// 用来测试创建 /eclipse 节点
    	private static final String PATH = "/eclipse";
    	public ZooKeeper zkClient = null; 
    	
    	/**
    	 * 初始化 Zookeeper 对象
    	 * @throws Exception
    	 */
    	@Before
    	public void init() throws Exception {
    		// 第三个参数为回调函数
    		zkClient = new ZooKeeper(CONNECT_STRING, SESSION_TIMEOUT, new Watcher() {
    			@Override
    			public void process(WatchedEvent event) {
    				// 收到事件通知后的回调函数
    				System.out.println(event.getType() + "---" + event.getPath());
    			}
    		});
    	} 
    	
    	/**
    	 * 创建 znode
    	 * @throws KeeperException
    	 * @throws InterruptedException
    	 */
    	@Test
    	public void testCreate() throws KeeperException, InterruptedException {
    		// 参数1: 要创建的节点的路径 参数2: 节点数据  参数3: 节点权限  参数4:节点的类型
    		zkClient.create(PATH, "zk-test".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    		zkClient.create(PATH + "/node1", "zk-node1".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    		zkClient.create(PATH + "/node2", "zk-node2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    	}
    	
    	/**
    	 * 获取PATH下的子znode列表
    	 * @throws KeeperException
    	 * @throws InterruptedException
    	 */
    	@Test
    	public void testGetChildren() throws KeeperException, InterruptedException {
    		List<String> children = zkClient.getChildren(PATH, true);
    		for(String child : children) {
    			System.out.println(child);
    		}
    	}
    	
    	/**
    	 * 获取PATH的znode的数据data
    	 * @throws KeeperException
    	 * @throws InterruptedException
    	 */
    	@Test
    	public void testGetData() throws KeeperException, InterruptedException {
    		byte[] data = zkClient.getData(PATH, true, null);
    		System.out.println(new String(data));
    	}
    	
    	/**
    	 * 判断节点路径是否存在
    	 * @throws KeeperException
    	 * @throws InterruptedException
    	 */
    	@Test
    	public void testExist() throws KeeperException, InterruptedException {
    		// 存在则返回Stat 元数据对象, 不存在返回null
    		Stat exists = zkClient.exists(PATH, false);
    		System.out.println(exists);
    		System.out.println(exists == null ? "not exist" : "exist");
    	}
    	
    	/**
    	 * 删除叶子节点, 若路径参数不为叶子节点,删除会报错.
    	 * Zookeeper对象 不支持删除非叶子节点,只能删除完子节点,才能删除父节点
    	 * @throws InterruptedException
    	 * @throws KeeperException
    	 */
    	@Test
    	public void testDelete() throws InterruptedException, KeeperException {
    		// 参数1: 删除的节点路径  参数2: 指定删除的版本, -1表示删除所有版本
    		zkClient.delete(PATH+"/node1", -1);
    	}
    	
    	
    	/**
    	 * 修改路径节点数据
    	 * @throws Exception
    	 * @throws InterruptedException
    	 */
    	@Test
    	public void testSetZnode() throws Exception, InterruptedException {
    		zkClient.setData(PATH, "modify".getBytes(), -1);
    		
    		byte[] data = zkClient.getData(PATH, false, null);
    		System.out.println(new String(data));
    	}
    }
    

    4.2.2 模拟系统服务器上下线动态感知

    原理:
    服务器端:服务器上线就在zookeeper的/server路径下创建一个EPHEMERAL_SEQUENTIAL类型的znode,znode的data值设为服务器名字。由于znode为短暂类型,当服务器下线,则对应的znode会被自动删除。
    客户端: 获取与zookeeper的连接,获取zookeeper的/server路径下的znode,这些znode就为在线的服务器,并对/server路径设置监听,当/server路径下的节点发生变化,则重新获取/server下的节点列表,更新在线服务器列表。

    客户端: DistributeClient
    服务端 : DistributedServer

    4.2.3 模拟实现分布式锁

    原理:每个服务器上线在zookeeper的/server路径下生成一个带序号的自动递增短暂节点,客户端使用时取序号最小的服务器,使用完毕后删除该序号最小服务器节点,然后重新生成该服务器节点,下次使用继续取服务器序号最小节点,效果类似轮询。
    DistributeClientLock

  • 相关阅读:
    安卓虚拟机AVD启动报错:Running an x86 based Android Virtual Device (AVD) is 10x faster
    Android ADT 下载 ( ADT23.0.7 )
    安卓APP_android_params.gravity无法解析gravity
    电容麦与其他麦克风有什么不同?
    理解Kubernetes编排架构
    k8s(四)—service服务(暴露方式:ClusterIP、NodePort、LoadBalancer、ExternalName、ingress)
    k8s基础概念
    k8s 查看ip地址属于哪个pod_k8s之PodIP、ClusterIP和ExternalIP
    Helm 是 Kubernetes 的包管理器
    定义统一响应对象
  • 原文地址:https://www.cnblogs.com/jxkun/p/9375265.html
Copyright © 2020-2023  润新知