Zookeeper注册中心

一、Zookeeper介绍

        Zookeeper是一个分布式协调系统,主要是为分布式软件提供一致性协调服务,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

1.功能

  • 为别的分布式提供服务
  • 本身就是一个分布式程序
  • 主从协调,服务器节点动态上下线,统一配置管理,分布式共享锁,统一名称服务
  • 管理(存储,读取)用户程序提交的数据,并为用户程序提供数据节点监听服务

2.Zookeeper的集群机制

        Zookeeper作为一个分布式协调系统,主要为其他分布式软件提供服务,因此它本身是非常重要的,所以Zookeeper不能随便挂掉,因此Zookeeper一般自身采用集群机制

        Zookeeper的集群机制为半数存活机制,即Zookeeper的多个集群节点,只有当过半的节点处于可用状态,才会对外提供服务,否则Zookeeper是不可用的。

3.Zookeeper集群机制的角色

3.1.Leader领导者

        Leader是Zookeeper集群工作机制的核心角色,主要工作为

  • 事务请求的唯一调度和处理者,保证集群事务处理的顺序性
  • 集群内部服务的调度者

3.2.Follower跟随者

        Follower是Leader的跟随者,主要工作为

  • 处理客户端非事务性请求(读取数据),转发事务请求给Leader服务器
  • 参与事务请求Proposal的投票
  • 参与Leader选举投票

3.3.Observer

        Observer充当观察者角色,观察Zookeeper集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进行独立处理,对于事务请求,则会转发给Leader服务器进行处理。Observer不会参与任何形式的投票,包括事务请求Proposal的投票和Leader选举投票

二、Zookeeper集群环境的搭建

1.下载解压tar包

#下载tar包
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.5.9/apache-zookeeper-3.5.9-bin.tar.gz
#解压
tar -zxvf apache-zookeeper-3.5.9-bin.tar.gz

2.移动到指定目录

mv apache-zookeeper-3.5.9-bin /root/soft/

3.修改配置

cd /root/soft/apache-zookeeper-3.5.9-bin/conf/
mv zoo_sample.cfg zoo.cfg
vim zoo.cfg

4.配置节点信息

        刚刚我们在zoo.cfg文件中配置了节点的信息,我们需要在Zookeeper的数据目录定义当前节点属于第几个节点,文件中的内容只有一行信息,即表示我们集群几点的标识,范围是1-255,每个节点的myid的数字和我们在zoo.cfg中配置的server.数字是对应的。

cd /root/soft/apache-zookeeper-3.5.9-bin/data
touch myid
vim myid

5.其他集群文件配置

        zookeeper的集群配置都是一样的,配置好一个后我们只需要将配置好的Zookeeper文件scp到别的服务器上,之后修改对应的myid即可。

6.启动测试

#启动
cd bin
./zkServer.sh start
#查看运行状态
./zkServer.sh status

  

三、Zookeeper的Leader选举机制

SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致

ZXID:事务ID,ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑有关

1.每一个 Server 都会发出一个投票

        在集群初次启动时,每个 Server 都会推荐自己为 Leader,然后各自将这个投票发给集群中其他 Server。

2.接收来自各个 Server 的投票

        每个 Server 在接收到其他 Server 的投票后,首先会判断该票的有效性,包括检查是否本轮投票,是否来自 Looking 状态的 Server。(Looking 状态表示当前集群正处于选举状态)

3.处理投票

        针对每一个投票,Server 都会将别人的投票和自己的投票进行 PK,计算出 Zxid 最大的 Server,并将该 Server 设置成下一次投票推荐的 Server。

4.统计投票

        每次投票结束之后,都会统计所有投票,获取投票最多的 Server 将成为获胜者,如果获胜者的票数超过集群个数的一半,则该 Server 将为推选为 Leader。否则继续投票,直至 Leader 被选举出来。

5.改变服务器状态

        一旦 Leader 确定后,Leader 会通知其他 Follower 集群已经成为 Uptodate 状态,Follower 在收到 Uptodate 消息后,接收 Client 的请求并开始对外提供服务。

四、Zookeeper客户端的使用

1.进入客户端

cd bin
./zkCli.sh

2.Zookeeper的数据结构

  1. 层次化的目录结构,命名符合常规文件系统规范

  2. 每个节点在Zookeeper中叫做znode,并且有一个唯一的路径标识

  3. 节点znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)

  4. 客户端应用可以在节点上设置监听器

3.Zookeeper的节点类型

znode有两种类型:

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

znode有四种形式的目录节点(默认是persistent)如下

序号节点类型描述
1PERSISTENT持久节点
2PERSISTENT_SEQUENTIAL持久有序节点
3EPHEMERAL短暂节点
4EPHEMERAL_SEQUENTIAL短暂有序节点

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

4.Zookeeper的常用命令

4.1.查看节点下的信息

ls [path]

4.2.查看节点下的详情信息

ls -s [path]

 

4.3.创建节点

create /app1 test

4.4.查看节点里的数据

get [path]

4.5.查看节点的具体信息

get -s [path]

4.6.删除没有子节点的节点

delete [path]

4.7.删除节点以及该节点下的子节点

deleteall [path]

4.8.修改节点里的数据

set [path] test

5.数据的监听

5.1.监听数据的改变

get -w [path]

5.2.监听节点的改变

ls -w [path]

五、Zookeeper的Java API使用

1.引入依赖

<dependencies>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.5.9</version>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

2.基本操作

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

/**
 * @Author: gesiyu
 * @Date: 2022-12-18  18:23
 * @Description: zookeeper测试
 */
public class ZookeeperTest {

    private String connectionString = "127.0.0.1:2181";

    private int sessionTimeOut = 50000;

    private ZooKeeper zooKeeper = null;

    /**
     * 建立连接
     *
     * @throws IOException io
     */
    @Before
    public void connectionTest() throws IOException {
        zooKeeper = new ZooKeeper(connectionString, sessionTimeOut, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("连接成功!");
            }
        });
        System.out.println(zooKeeper);
    }

    /**
     * 创建节点
     */
    @Test
    public void createTest() throws InterruptedException, KeeperException {
        //params:路径 数据 权限 类型
        String createPath = zooKeeper.create("/apptest", "love".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zooKeeper.create("/apptest/app1", "love".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zooKeeper.create("/apptest/app2", "love".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(createPath);
    }

    /**
     * 判断节点是否存在
     */
    @Test
    public void existsTest() throws InterruptedException, KeeperException {
        //params:节点路径 使用的watch
        Stat exists = zooKeeper.exists("/apptest", true);
        if (exists != null) {
            System.out.println("节点为:" + exists);
        } else {
            System.out.println("节点不存在");
        }
    }

    /**
     * 获取节点下的子节点
     */
    @Test
    public void childrenTest() throws InterruptedException, KeeperException {
        //params:节点路径 使用的watch
        List<String> zooKeeperChildren = zooKeeper.getChildren("/apptest", true);
        for (String keeperChild : zooKeeperChildren) {
            System.out.println(keeperChild);
        }
    }

    /**
     * 修改节点的内容
     */
    @Test
    public void setData() throws Exception{
        // -1 不指定版本 自动维护
        Stat stat = zooKeeper.setData("/apptest/app2", "666666".getBytes(), -1);
        System.out.println(stat);
    }

    /**
     * 删除节点
     */
    @Test
    public void deleteNode() throws Exception{
        zooKeeper.delete("/apptest/app1",-1);

    }

}

3.监听数据变化

/**
     * 监听Node节点下的子节点的变化
     */
    @Test
    public void nodeChildrenChange() throws Exception{
        List<String> list = zooKeeper.getChildren("/app1", new Watcher() {

            /**
             *              None(-1),
             *             NodeCreated(1),
             *             NodeDeleted(2),
             *             NodeDataChanged(3),
             *             NodeChildrenChanged(4),
             *             DataWatchRemoved(5),
             *             ChildWatchRemoved(6);
             * @param watchedEvent
             */
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("--->"+ watchedEvent.getType());
            }
        });
        for (String s : list) {
            System.out.println(s);
        }

        Thread.sleep(Integer.MAX_VALUE);
    }

    /**
     * 监听节点内容变更
     */
    @Test
    public void nodeDataChanged() throws Exception{
        byte[] data = zooKeeper.getData("/app1/a1", new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("--->" + watchedEvent.getType());
            }
        }, null);
        System.out.println("--->" + new String(data));
        Thread.sleep(Integer.MAX_VALUE);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值