Zookeeper 笔记

一、引言


在分布式环境下,如果舍弃SpringCloud,使用其他的分布式框架,那么注册心中,配置集中管理,集群管理,分布式锁,分布式任务,队列的管理想单独实现怎么办。

CAP理论

在分布式系统中出现一种理论,C一致性Consistncy,A可用性Availability,P分区容错性Partition tolerance

1.一致性

在分布式系统中,有很多节点,一致性指的是所有的节点数据保证是一样的,如果出现了不一样就会导致不一致性

2.可用性

当我们请求集群中的任意一台服务器的时候,都应该有一个正常的响应结果

3.分区容错性

比如百度在北上广深都有服务器集群,他们会给就近的用户提供数据,同时他们之间会相互同步数据,假如北京和上海的网络出现了故障无法同步
这种情况下,北京和上海的集群仍然可以对就近的人提供数据,只是他们两个之间无法交换数据,导致就近的人无法获取另外一个地方的数据而已

EUREKA

在CAP理论中,eureka是遵从ap的

Zookeeper

主要保证是CP,但是它要求的是超过一半的服务器一致就可以

二、Zookeeper介绍


Zookeeper本身是Hadoop生态园的中的一个组件,Zookeeper强大的功能,在Java分布式架构中,也会频繁的使用到Zookeeper。

Zookeeper就是一个文件系统 + 监听通知机制

三、Zookeeper安装


docker-compose.yml

version: "3.1"
services:
  zk:
   image: daocloud.io/daocloud/zookeeper:latest
   restart: always
   container_name: zk
   ports:
     - 2181:2181

四、Zookeeper架构【重点


4.1 Zookeeper的架构图
  • 每一个节点都没称为znode
  • 类标准文件系统
  • 每一个znode中都可以存储数据
  • 节点名称是不允许重复的
Zookeeper的架构图
在这里插入图片描述
4.2 znode类型

四种Znode

  • 持久节点:永久的保存在你的Zookeeper

  • 持久有序节点:永久的保存在你的Zookeeper,他会给节点添加一个有序的序号。 /xx -> /xx0000001

  • 临时节点:当存储的客户端和Zookeeper服务断开连接时,这个临时节点自动删除

  • 临时有序节点:当存储的客户端和Zookeeper服务断开连接时,这个临时节点自动删除,他会给节点添加一个有序的序号。 /xx -> /xx0000001

4.3 Zookeeper的监听通知机制

客户端可以去监听Zookeeper中的Znode节点。

Znode改变时,会通知监听当前Znode的客户端

监听通知机制
在这里插入图片描述

五、Zookeeper常用命令


Zookeeper针对增删改查的常用命令

# 查询当前节点下的全部子节点
ls 节点名称
# 例子 ls /


# 查询当前节点下的数据
get 节点名称
# 例子 get /zookeeper


# 创建节点
create [-s] [-e] znode名称 znode数据
# -s:sequence,有序节点
# -e:ephemeral,临时节点


# 修改节点值
set znode名称 新数据


# 删除节点
delete znode名称    # 没有子节点的znode
rmr znode名称      # 删除当前节点和全部的子节点

六、Zookeeper集群【重点


6.1 Zookeeper集群架构图
集群架构图
在这里插入图片描述
6.2 Zookeeper集群中节点的角色
  • Leader:Master主节点
  • Follower (默认的从节点):从节点,参与选举全新的Leader
  • Observer:从节点,不参与投票
  • Looking:正在找Leader节点
6.3 Zookeeper投票策略
  • 每一个Zookeeper服务都会被分配一个全局唯一的myid,myid是一个数字。

  • Zookeeper在执行写数据时,每一个节点都有一个自己的FIFO的队列。保证写每一个数据的时候,顺序是不会乱的,Zookeeper还会给每一个数据分配一个全局唯一的zxid,数据越新zxid就越大。

选举Leader:

  • 选举出zxid最大的节点作为Leader。
  • 在zxid相同的节点中,选举出一个myid最大的节点,作为Leader。
6.4 搭建Zookeeper集群

yml文件

version: "3.1"
services:
  zk1:
    image: zookeeper
    restart: always
    container_name: zk1
    ports:
      - 2181:2181
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181
  zk2:
    image: zookeeper
    restart: always
    container_name: zk2
    ports:
      - 2182:2181
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181
  zk3:
    image: zookeeper
    restart: always
    container_name: zk3
    ports:
      - 2183:2181
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181

七、Java操作Zookeeper


7.1 Java连接Zookeeper

创建Maven工程

导入依赖

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

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

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

编写连接Zookeeper集群的工具类

public class ZkUtil {

    public static CuratorFramework cf(){
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,2);
        CuratorFramework cf = CuratorFrameworkFactory.builder()
                .connectString("192.168.199.109:2181,192.168.199.109:2182,192.168.199.109:2183")
                .retryPolicy(retryPolicy)
                .build();

        cf.start();

        return cf;
    }

}

测试类

测试
在这里插入图片描述
7.2 Java操作Znode节点

查询

public class Demo2 {

    CuratorFramework cf = ZkUtil.cf();

    // 获取子节点
    @Test
    public void getChildren() throws Exception {
        List<String> strings = cf.getChildren().forPath("/");

        for (String string : strings) {
            System.out.println(string);
        }
    }

    // 获取节点数据
    @Test
    public void getData() throws Exception {
        byte[] bytes = cf.getData().forPath("/");
        System.out.println(new String(bytes,"UTF-8"));
    }

}

添加

@Test
public void create() throws Exception {
    cf.create().withMode(CreateMode.PERSISTENT).forPath("/2","uuuu".getBytes());
}

修改

@Test
public void update() throws Exception {
    cf.setData().forPath("/2","oooo".getBytes());
}

删除

@Test
public void delete() throws Exception {
    cf.delete().deletingChildrenIfNeeded().forPath("/2");
}

查看znode的状态

@Test
public void stat() throws Exception {
    Stat stat = cf.checkExists().forPath("/");
    System.out.println(stat);
}
7.3 监听通知机制

实现方式

public class Demo3 {

    CuratorFramework cf = ZkUtil.cf();


    @Test
    public void listen() throws Exception {
        //1. 创建NodeCache对象,指定要监听的znode
        NodeCache nodeCache = new NodeCache(cf,"/");
        nodeCache.start();

        //2. 添加一个监听器
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                byte[] data = nodeCache.getCurrentData().getData();
                Stat stat = nodeCache.getCurrentData().getStat();
                String path = nodeCache.getCurrentData().getPath();

                System.out.println("监听的节点是:" + path);
                System.out.println("节点现在的数据是:" + new String(data,"UTF-8"));
                System.out.println("节点状态是:" + stat);

            }
        });

        System.out.println("开始监听!!");
        //3. System.in.read();
        System.in.read();
    }

}
           String path = nodeCache.getCurrentData().getPath();

            System.out.println("监听的节点是:" + path);
            System.out.println("节点现在的数据是:" + new String(data,"UTF-8"));
            System.out.println("节点状态是:" + stat);

        }
    });

    System.out.println("开始监听!!");
    //3. System.in.read();
    System.in.read();
}

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值