zookeeper系列基础

Zookeeper

第一章 Zookeeper入门

概述

zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目

工作机制

​ zookeeper从设计模式角度来理解:是一个基于观察者模式,它负责和管理大家都关心的数据,然后接受观察者注册,一旦这些数据状态发生变化,zookeeper就将负责通知已经在zookeeper上注册的那些观察者做出响应的反应.

zookeeper=文件系统+通知机制.

在这里插入图片描述

特点

在这里插入图片描述

1.Zookeeper:一个领导者(Leader),多个跟随着(Follower),组成集群

2.集群中只要有半数以上节点存货,zookeeper集群就能正常的服务

3…全局的数据是一致的:每个server保存一份相同的数据副本,Client无论连接到哪个Server数据都是一致的.

4.更新 请求顺序进行,来自同一个Client的更新请求按其发送顺序进行

5.数据更新原子性,一次数据更新要么成功,要么失败

6.实时性,在一定时间范围内,client能读到最新的数据

数据结构

在这里插入图片描述

​ Zookeeper的数据结构与unix非常相似,整体上可以看作一棵树,每个节点称作一个znode.每个znode默认能够存储1MB数据.每个znode都可以通过其路径唯一标识

应用场景

提供的服务:统一命名服务,统一配置管理,统一集群管理,服务器节点动态上下线,软负载均衡

统一命名服务

​ 在分布式环境下,经常需要对应用/服务进行统一命名,便于识别.

​ 例如:IP不容易记住,而域名容易记住
在这里插入图片描述

统一配置管理

1.分布式环境下,配置文件同步是非常常见的

A.一般要求一个集群中,所有的节点的配置信息是一致的

b.对配置的文件修改后,希望能够快速的同步到各个节点上

2.配置文件可以交给zookeeper来做

A.可以将配置的信息写入Zookeeper上的一个Znode

B.各个客户端服务器监听这个znode(监听机制)

在这里插入图片描述

对上面的图进行解释:就是我的配置文件信息交给zookeeper管理,我的多个客户端进行读取并且监听这个文件信息的变换,一旦这个配置信息发生变化,客户端就会得到一个通知,然后就是process().写自己的逻辑代码,来处理这个变化.

统一集群管理

1.分布式环境下,实时掌握每个节点的变化是非常有必要的

A.可根据节点的实时状态做出一些响应的调整

2.Zookeeper可以实现实时监控节点状态的变化

A.可将节点信息写入Zookeeper上的一个Znode

B.监听这个Znode可以获取到它的实施状态的变化.

服务器动态上下线

客户端实时观察服务器上下线的变化

在这里插入图片描述

软负载均衡

在这里插入图片描述

zookeeper的下载

下载地址

Zookeeper集群的安装

博文中有

在这里插入图片描述

第二章 Zookeeper内部原理

选举机制

1.半数机制:集群中半数以上的集群存货,集群可用,所以zookeeper适合安装奇数

台服务器.

2.zookeeper虽然在配置文件中没有指定master和slave,但是,zookeeper工作时,但是有一个节点为leader的,其他的为follower,Leadder是通过内部选举机制临时产生的

3.简单的例子

假如有五台服务器组成的zookeeper集群,他们的id是从1–5,同时他们都是最新启动的,也就是没有历史数据,在存数量这一点上,都是一样的,假设这些服务器一次启动,来看看会怎么样

在这里插入图片描述

过程

1>server1启动,此时只有它一台启动,它发出去的报文没有回应,所以它的选举一直处在LOOKING状态

2>server2启动,此时它与最开始启动的server1进行通信,相互交换自己的选举结果,由于两者都没有历史数据,所以id值较大的server2胜出,但是由于没有达到半数以上,所以它的选举也处在LOOKING状态

3>server3启动,此时它与server1和server2分别交换选举结果,超过半数,称为Leader’

4>server4启动,但是此时分别于server1,2,3交换选举信息,但是发现server3已经成为Leader,所以只能成为Follower

5>和server4一样

节点的类型

持久:持久目录节点

客户端于服务器断开连接,创建的节点不会删除.

1.持久化目录节点

客户端与zookeeper断开连接,该节点依旧存在

2.持久化顺序编号目录节点

客户端与zookeeper断开连接,该节点依旧存在,只是zookeeper给该节点进行顺序编号.

命令

create -s /sanguo/weiguo

结果

Created /sanguo/weiguo0000000005

注意**:创建znode时设置顺序标识,znode名称后会附加一个值,顺序编号是一个单调递增的计数器,有父节点维持

在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端就可以通过顺序号推断事件的顺序.

短暂:临时目录节点

客户端与服务器断开节点,创建的节点自己删除.

1.临时化目录节点

客户端与zookeeper断开连接,该节点依旧不存在

2.临时顺序编号目录节点

客户端与zookeeper断开连接,该节点不存在,只是zookeeper给该节点进行顺序编号.

验证

create -s -e /sanguo/weiguo

结果

Created /sanguo/weiguo0000000006

退出重新进来

quit
./zkCli.sh
ls /sanguo

结果

[shuguo, weiguo0000000002, weiguo0000000003, weiguo0000000005]

发现并不存在 /sanguo/weiguo0000000006节点

注意:顺序号是从临时节点,持久节点顺序号一块使用的.

第三章 zookeeper实际操作

集群的搭建

命令操作

1.启动服务端

./zkserver start

2.启动客户端

./zkCli.sh

3.显示所有操作命令

help

4.查看节点信息

ls path
//节点的详细信息
ls2 path

5.创建两个节点

create path 数据

注意:如果节点上没有数据就会创建失败,还有就是上面创建的是持久节点

6.获得数据

get path

7.创建短暂的数据节点

create -e path 数据

所谓的短暂节点,就是quit之后重新客户端连接服务端,节点就自动删除了.

8.创建带有序号的节点

create -s path 数据

sequence : 顺序

9.监听节点数据(信息)变化,指的是至少两台服务器之间的数据监听

//这个过时了
get path watch
//新的为
get -w path
//例如
get -w /sanguo/shuguo

在另一台服务器上

set path 数据

结果

WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo/shuguo

10.监听路径,即子节点的变化

ls -w path

例如

在zoo_node1上

ls -w /sanguo

在zoo_node2上

create /sanguo/weiguo "caocao"

在zoo_node1上显示的结果是

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo

注意:监听只有一次有效,下次要想再监听得重新创建.

11.递归删除

rmr path

12.删除节点

delete path

13.help所有的最新命令

 addauth scheme auth
        close 
        config [-c] [-w] [-s]
        connect host:port
        create [-s] [-e] [-c] [-t ttl] path [data] [acl]
        delete [-v version] path
        deleteall path
        delquota [-n|-b] path
        get [-s] [-w] path
        getAcl [-s] path
        history 
        listquota path
        ls [-s] [-w] [-R] path
        ls2 path [watch]
        printwatches on|off
        quit 
        reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
        redo cmdno
        removewatches path [-c|-d|-a] [-l]
        rmr path
        set [-s] [-v version] path data
        setAcl [-s] [-v version] [-R] path acl
        setquota -n|-b val path
        stat [-w] path
        sync path

stat结构体

在这里插入图片描述

常用的:dataLength-znode的数据长度

​ numChildren-zndoe子节点的数量

监听器的原理

1.原理详解

1>首先要有一个main()线程

2>在main()线程中创建Zookeeper客户端,这是就会创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener)

3>t通过connect线程将注册的监听事件发给zookeeper

4>在zookeeper的注册监听器列表中将注册的监听事件添加到列表中

5>zookeeper监听到的数据或路径发生变化,就会将这个消息发送给listener线程

6>listner线程调用内部的process()方法.

在这里插入图片描述

2.常见的监听

1>监听节点数据的变化

get -w /path

2>监听子节点增减的变化

ls -w /path

写数据的流程

在这里插入图片描述

第四章 实际操作

加依赖

 <dependency>
     <groupId>com.101tec</groupId>
     <artifactId>zkclient</artifactId>
     <version>0.10</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

创建zkClient

@SpringBootApplication
public class ZookeeperApplication {
    private String connecStr = "39.97.252.228:2181,39.97.252.228:2182,39.97.252.228:2183";
    private int sessionTimeout = 5000;
    private ZooKeeper zkCli;
    @Bean
    public ZooKeeper zooKeeper(){
        ZooKeeper zkClient = null;
        try {
            zkClient =  new ZooKeeper(connecStr, sessionTimeout, new Watcher() {
                 @Override
                 public void process(WatchedEvent watchedEvent) {
                 }
             });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zkClient;
    }

    public static void main(String[] args) {
        SpringApplication.run(ZookeeperApplication.class,args);
    }
}

添加节点

@SpringBootTest
public class MyTest {
    @Autowired
    private ZooKeeper zkClient;
    /**
     * 本测试用于向zookeeper添加节点
     * @throws KeeperException
     * @throws InterruptedException
     * @throws IOException
     */
    @Test
    public void create() throws KeeperException, InterruptedException, IOException {
        String path = zkClient.create("/sanguo/wangguo", "你好世界".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(path);
    }
}

总结:上面的参数的意思是:

1.第一个是创建节点的固定格式

create path 数据

2.第二个是数据利String中的getBytes(),把字符串转换成byte[]数组

3.ZooDefs.Ids.OPEN_ACL_UNSAFE:节点权限问题,这里设置为谁都可以读

4CreateMode.PERSISTENT:节点得类型,四种短暂得两种:带序号和不带序号的,持久得两种:带序号和不带序号的.

CreateMode.EPHEMERAL
CreateMode.EPHEMERAL_SEQUENTIAL
CreateMode.PERSISTENT
CreateMode.PERSISTENT_SEQUENTIAL

ephemeral :短暂的

sequential:有序的

persistent:持久的

获取子节点并监视子节点

1.获取子节点

   /**
     * 本测试用于测试子节点的获得
     * @throws KeeperException
     * @throws InterruptedException
     */
    @Test
    public void getChildren() throws KeeperException, InterruptedException {
        List<String> nodes = zkClient.getChildren("/", false);
        for(String str : nodes){
            System.out.println(str);
        }
    }

结果是

dubbo
zookeeper
sanguo

2.获取并且监视

public class ZkClientLession {
    private String connectStr = "39.97.252.228:2181,39.97.252.228:2182,39.97.252.228:2183";
    private int sessionTimeout = 5000;
    private ZooKeeper zkCli;

    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        ZkClientLession client = new ZkClientLession();
        /**
         * 获取zookeeper连接
         */
        client.createZkCli();
        /**
         * 注册监听
         */
        client.getChildrenNodes();
        /**
         * 业务逻辑处理
         */
        client.buiness();
    }

    private void buiness() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    public void getChildrenNodes() throws KeeperException, InterruptedException {
        List<String> nodes = zkCli.getChildren("/", true);
        for(String str : nodes){
            System.out.println(str);
        }
    }

    public void createZkCli() throws IOException {
        zkCli = new ZooKeeper(connectStr, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                try {
                    getChildrenNodes();
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

测试

    /**
     * zookeeper的监听机制
     *1>首先要有一个main()线程
     * 2>在main()线程中创建Zookeeper客户端,这是就会创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener)
     * 3>t通过connect线程将注册的监听事件发给zookeeper
     * 4>在zookeeper的注册监听器列表中将注册的监听事件添加到列表中
     * 5>zookeeper监听到的数据或路径发生变化,就会将这个消息发送给listener线程
     * 6>listner线程调用内部的process()方法.
     */
    @Test
    public void getChildrenAndWatch() throws KeeperException, InterruptedException {
        List<String> nodes = zkClient.getChildren("/", true);
    }

在这里插入图片描述

节点是否存在

 @Test
    public void zkClientExit() throws KeeperException, InterruptedException {
        Stat exists = zkClient.exists("/sanguo", false);
        System.out.println(exists);
    }

服务上下线

在这里插入图片描述

服务的注册

三步:

1.连接zookeeper,上面有

2.注册服务,用到的是

create path 数据

java中用到的是create节点,需要注意的是create创建的是临时节点.

3.业务逻辑的处理

服务的使用

三步,简单的网上搜搜看看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值