zookeeper的基本使用与常用配置

Zookeeper安装

安装zookeeper

version: "3.1"
services:
  zk:
    image: daocloud.io/daocloud/zookeeper:latest    # 其实是3.4.6版本的Zookeeper
    container_name: zk
    ports:
      - 2181:2181

进入到zookeeper容器内部,打开客户端

docker exec -it zk bash
cd bin
./zkCli.sh

Zookeeper常用命令

# 查询当前节点下的全部子节点
ls 节点名称
# 例子 ls /
# 查询当前节点下的数据
get 节点名称
# 例子 get /zookeeper
# 创建结点
create [-s] [-e] znode名称 znode数据

# -s:sequence,有序节点
# -e:ephemeral,临时节点
# 例如 create /zookeeper/zbx zhang
# 修改结点
set znode名称 新数据
# 删除结点
delete znode名称    # 没有子节点的znode
deleteall znode名称
rmr znode名称      # 删除当前节点和全部的子节点

Zookeeper架构

每一个目录都可以称为一个znode,每个znode都可以有子节点,每个znode都能存储数据

znode类型

  • 持久结点
  • 持久有序结点
  • 临时结点
  • 临时有序结点

Zookeeper提供了监听通知机制,客户端在监听某一个ZNode节点后,当这个ZNode被修改/删除后,Zookeeper会立即通知整个客户端,并执行客户端的回调函数。

Zookeeper集群

集群中结点的角色

1、 Leader

  • Master主节点,可读可写

2、 Follower (默认的从节点)

  • 从节点,可以读,如果请求为写,则转发给Leader;参与选举全新的Leader

3、 Observer

  • 从节点,可以读,如果请求为写,则转发给Leader;不参与投票

4、 Looking

  • 寻找Leader节点

集群中,如果Leader宕机,则集群不提供任何功能,此时集群内部会发起投票,选取一位全新的Leader

Zookeeper投票策略

1、每一个Zookeeper服务都会被分配一个全局唯一的myid,myid是一个数字。

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

选举Leader:

  1. 选举出zxid最大的节点作为Leader。
  2. 在zxid相同的节点中,选举出一个myid最大的节点,作为Leader。

搭建Zookeeper集群

(Zookeeper搭建集群采用的3.6.2版本)

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

导入依赖

<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>
</dependencies>

编写连接工具类

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;
    }
}

操作结点

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("/qf");
        System.out.println(new String(bytes,"UTF-8"));
    }
    
    // 添加
    @Test
    public void create() throws Exception {
        cf.create().withMode(CreateMode.PERSISTENT).forPath("/qf2","uuuu".getBytes());
    }
    
    // 修改
    @Test
    public void update() throws Exception {
        cf.setData().forPath("/qf2","oooo".getBytes());
    }
    
    // 删除
    @Test
    public void delete() throws Exception {
        cf.delete().deletingChildrenIfNeeded().forPath("/qf2");
    }
    
    // 查询znode状态
    @Test
    public void stat() throws Exception {
        Stat stat = cf.checkExists().forPath("/qf");
        System.out.println(stat);
    }

}

监听通知机制

public class Demo3 {

    CuratorFramework cf = ZkUtil.cf();

    @Test
    public void listen() throws Exception {
        //1. 创建NodeCache对象,指定要监听的znode
        NodeCache nodeCache = new NodeCache(cf,"/qf");
        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();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值