Zookeeper基础知识

Zookeeper

https://zookeeper.apache.org/

节点znode(基本数据类型)

树形结构,类似linux的文件目录

每一个节点都是znode,里面可以包含数据,也可以有子节点

节点分为永久节点临时节点(session失效,也就是客户端断开后,临时节点消失)

每个znode都有版本号,每当数据变化,版本号会累加(乐观锁)

删除或修改节点,当版本号不匹配(版本号已过时),则会报错

每个节点存储的数据不宜过大,几K即可

节点可以设置权限,来限制用户的访问

Zookeeper保证读和写都是原子操作,且每次读写操作都是对数据的完整读取或写入

节点类型

持久节点:创建时进行设置,不允许再改变类型;只能显示删除,否则一直存在

临时节点:依赖于客户端回话,断开连接自动删除,也可手动删除;可以利用临时节点方便的进行集群管理,比如每一个临时节点代表一个服务实例,服务宕机时临时节点被删除,维护服务发现的功能。

顺序节点:持久节点和临时节点都可以是顺序的或非顺序的,如果创建一个持久或临时的顺序节点,会生成一个10位的分布式唯一ID

节点属性

dataVersion 数据版本

cversion 子节点版本

aclVersion 权限控制版本

···

常用命令

启动

./bin/zkServer.sh start

停止

./bin/zkServer.sh stop

重启

./bin/zkServer.sh restart 

连接到服务器

./bin/zkCli.sh -server 127.0.0.1:2181

连接后输入help可查看命令

查看指定节点目录下节点内容

ls path

查看节点状态

stat path

创建节点

-s 顺序节点 -e 临时节点

create [-s] [-e] [-c] [-t ttl] path [data] [acl]

查看节点数据

get path

修改节点数据

set [-s] [-v version] path data

删除

delete [-v version] path

Watcher机制

触发器、监督者

触发器,监听节点变化通知客户端

使用zookeeper自带的客户端实现是临时的用过一次后销毁,使用apache客户端的可以永久性

使用场景:统一资源配置

例如多个client把redis的client和端口号信息存到zookeeper上,如果没有watcher,只能不断轮询,比如几秒钟查一次,不可靠且开销大;使用watcher数据变化后会通知client

Zookeeper基础知识_第1张图片

Watcher事件类型

Zookeeper基础知识_第2张图片

ACL(access control list)权限控制

它使用权限位来允许/禁止对节点及其所有作用域的各种操作

ACL仅与特定的znode有关,与子节点无关;比如设置一个节点只能被某ip读取,但是其子节点不受影响

Scheme

ACL:[scheme采用的权限机制:id用户:permissions权限组合字符串]

world

auth

digest

ip

super

权限字符串crdwa

create

read

delete

write

admin

权限使用场景

区分开发/测试/运维环境,防止误操作

可以针对不同IP而产生具体的配置,更安全;代价是IP变化需要再配置

Java原声客户端连接到ZK

依赖

<dependency>
  <groupId>org.apache.zookeepergroupId>
  <artifactId>zookeeperartifactId>
  <version>3.8.0version>
dependency>

日志配置

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss} %p %c{2}: %m%n

建立连接

package com.test.zookeeper;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;

public class ZKConnect implements Watcher {
    //连接ZK所在的客户端服务器ip
    public static final String SERVER_PATH = "ip:2181";
    // 设置超时时间
    public static final Integer TIME_OUT = 5000;

    // 重写Watcher接口方法:
    @Override
    public void process(WatchedEvent watchedEvent) {
        System.out.println("收到了通知"+watchedEvent);}

    public static void main(String[] args) throws IOException, InterruptedException {
        // 连接zk客户端:
        ZooKeeper zk = new ZooKeeper(SERVER_PATH, TIME_OUT, new ZKConnect());
        // 打印连接的状态:
        System.out.println("正在连接ZK客户端");
        System.out.println(zk.getState());
        Thread.sleep(2000);
        System.out.println(zk.getState());  //连接成功 CONNECTED
    }
}

对节点进行操作

public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
  // 连接zk客户端:
  ZooKeeper zk = new ZooKeeper(SERVER_PATH, TIME_OUT, new ZKConnect());
  /**
         * path:创建的路径
         * data:数据
         * acl:权限,开放
         * createMode:永久、临时、顺序节点
         */
  zk.create("/mytest", "mynode".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
  //修改节点 原节点 要修改的内容 版本号
  //        zk.setData("/mytest", "mytest2".getBytes(), 0);

  //        zk.delete("/mytest2", 2);     //要返回删除信息可以自定义CallBack回掉函数
  //获取节点
  byte[] data = zk.getData("/mytest", null, null);
  System.out.println(new String(data));
}

处理Watcher事件

原生JavaAPI的缺点

不支持连接超时后的自动重连

Watcher注册一次后会失效

不支持递归创建节点

利用Apache Curator作为客户端来操作ZK

依赖

<dependency>
  <groupId>org.apache.curatorgroupId>
  <artifactId>curator-frameworkartifactId>
  <version>2.12.0version>
dependency>

用Curator操作ZK

package com.test.zookeeper.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;

/**
 * 用Curator操作ZK
 */
public class CuratorTests {
    public static void main(String[] args) throws Exception {
        String connectString = "82.156.22.230:2181";
        RetryPolicy retry = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retry);
        client.start();
        //监听器
        client.getCuratorListenable().addListener((CuratorFramework c, CuratorEvent event)->{
            switch (event.getType()) {
                case WATCHED:
                    WatchedEvent watchedEvent = event.getWatchedEvent();
                    if (watchedEvent.getType() == Watcher.Event.EventType.NodeDataChanged) {
                        System.out.println(new String(c.getData().forPath(event.getPath())));
                    }
            }
        });

        String path = "/my_test_node";
        String data = "test_data";
        String data2 = "test_data2";
        client.create().withMode(CreateMode.PERSISTENT).forPath(path, data.getBytes()); //创建
        byte[] bytes = client.getData().watched().forPath(path);  //获取
        System.out.println(new String(bytes));

        client.setData().forPath(path, data2.getBytes());   //修改
        client.delete().forPath(path);  //删除
        Thread.sleep(2000);
    }
}

你可能感兴趣的:(java,web,zookeeper,bash,linux)