zookeeper简单入门

一、zookeeper的简介

ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了:分布式锁服务配置维护、组服务、分布式消息队列分布式通知/协调等。

zookeeper是一个使用树形结构的数据库,可以拥有高可用的集群,80%在读 ,20%在写,只允许在一台机器上写,机器分为两种角色 leader(领导者)+foollower(追随者),写由leader写入,读由foollower负责 ,一个集群只能有一个leader,leader由paxos算法选举出来,票数最高的机器成为leader。leader写入的数据通过paxos算法将所有数据同步,zookeeper的集群必须是2n+1台,最少n=1。

 

二、zookeeper能做什么

zookeeper功能非常强大,可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理等功能,我们这里拿比较简单的分布式应用配置管理为例来说明。

假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 zookeeper 的通知,然后从 zookeeper 获取新的配置信息应用到系统中。

 

三、zookeeper的特征

ZooKeeper采用了类似文件系统的的数据模型,其节点构成了一个具有层级关系的树状结构。

例如,下图展示了zk节点的层级树状结构。

图中,根节点 / 包含了两个子节点 /module1,/module2,而节点 /module1 又包含了三个子节点 /module1/app1,/module1/app2,/module1/app3。在zk中,节点以绝对路径表示,不存在相对路径,且路径最后不能以 / 结尾(根节点除外)。

zookeeper有四种znode 

  • 持久节点(PERSISTENT):创建后永久存在,除非主动删除。

create /path data
  • 临时节点(EPHEMERAL):临时创建的,会话结束节点自动被删除,也可以手动删除,临时节点不能拥有子节点

create -e /path value
  • 临时顺序节点(EPHEMERAL_SEQUENTIAL):具有临时节点特征,但是它会有序列号,分布式锁中会用到该类型节点

create -e -s /path data
  • 持久顺序节点(PERSISTENT_SEQUENTIAL):该节点创建后持久存在,相对于持久节点它会在节点名称后面自动增加一个10位数字的序列号,这个计数对于此节点的父节点是唯一,如果这个序列号大于2^32-1就会溢出。

create -s /path value

 

四、zookeeper安装  

1、单机模式安装

1、下载 安装包(http://www.apache.org/dyn/closer.cgi/zookeeper/) 这里建议下载3.4以上版本 (将事务日志和快照数据拆分为不同目录 自动清除过期文件)

注意:再使用zookeeper之前必须配置JAVA_HOME的环境变量,不然是启动不了的。

2、根据个人喜好给zookeeper的bin目录设置到path中,方便敲命令。

3、拷贝 conf/zoo_sample.cfg文件重新命名为zoo.cfg。

zoo.cfg的参数讲解

# 心跳的时间间隔  
tickTime=2000
# 初始化同步数据要花费的时间 10个tickTime    
initLimit=10
# leader和foollower互相发送心跳检查对方失效的时间间隔   
syncLimit=5
# 数据存储的位置(需要自己事先创建一个文件夹,用来存储数据)
dataDir=D:\private\zookeeper-3.4.10\data
# 端口号  
clientPort=2181
#默认的连接数(可以根据自己的机器设置连接数)
#maxClientCnxns=60

 

4、运行 bin/zkServer

看到2181的端口都显示出来了说明我们已经给zookeeper的服务端启动了。

 

5.打开一个cmd窗口,连接zookeeper的客户端,也可以直接点击bin目录下的 zkCli.cmd 文件启动,默认是启动localhost

zkCli -server localhost:2181

这个时候我们就已经连接上了zookeeper服务。

 

 常用的数据操作命令(树结构节点数据的操作)

显示根节点下所有的节点(ls / )

[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]

创建一个永久user节点  节点的值是 boy(create /user boy)

[zk: localhost:2181(CONNECTED) 1] create /user boy
Created /user
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper, user]

获取/user节点的值(get /user)

[zk: localhost:2181(CONNECTED) 3] get /user
boy


重新设置user节点的值(set /user aaa)

 set /user aaa

 

[zk: localhost:2181(CONNECTED) 4] set /user aaa
cZxid = 0x4
ctime = Thu Apr 25 10:55:08 CST 2019
mZxid = 0x5
mtime = Thu Apr 25 10:57:58 CST 2019
pZxid = 0x4
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: localhost:2181(CONNECTED) 5] get /user
aaa
cZxid = 0x4
ctime = Thu Apr 25 10:55:08 CST 2019
mZxid = 0x5
mtime = Thu Apr 25 10:57:58 CST 2019
pZxid = 0x4
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0

【通过命令 添加node后  可以查看到一些列 这些列的意义 】

 cZxid:节点创建时的zxid

ctime:  节点创建时间

mZxid:节点最近一次更新时的zxid

mtime:节点最近一次更新的时间

cversion:子节点数据更新次数

dataVersion:本节点数据更新次数

aclVersion:节点ACL(授权信息)的更新次数

ephemeralOwner:如果该节点为临时节点,ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是临时节点,ephemeralOwner值为0

dataLength:节点数据长度,本例中为hello world的长度

numChildren子节点个数

删除节点(delete /user)

[zk: localhost:2181(CONNECTED) 6] delete /user
[zk: localhost:2181(CONNECTED) 7] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 8]

其他命令

 help: 查看所有命令的帮助

 close/quit: 退出登录

 connect ip:port :重新登录

 histroy: 查看操作历史记录  每个历史记录都有一个编号

 redo: 编号  重新执行history中编号对应的语句

  close: 关闭客户端连接

  stat /user: 查看znode的/user的状态信息 

  ls2 /user: 查看/user所有的子节点 同时查看状态信息

  rmr /user: 删除/user以及他的所有子节点

  setquota -n 1 /test:  给/test节点设置允许的子节点个数是1个 添加子节点操作1个 给予警告 可以添加

                  -b 10 /test 给/test的值的长度限制为 10个字节 

  listquota /test: 列出/test所有的配额

  delquota -n /test: 删除子节点设置的配额

 

2、 集群模式安装

待更新。。。。。。。。。。。。。。。。。。。。。。。。。。

 

五、Zkclient客户端

1、创建maven项目 ,在pom.xml中加入zkclient的架包,为了方便演示,顺便加了个mysql依赖

    <dependencies>
        <!--添加mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>

        <!--添加zookeeper客户端依赖-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
    </dependencies>

2、创建测试类,演示一下zookeeper的监控功能,以连接数据库为例

package cn.et;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer;

import java.sql.*;

public class ZookeeperTest {
    private static byte [] url;
    private static byte [] driverClass;
    private static byte [] userName;
    private static byte [] password;
    private static Connection connction;
    private static ZkClient zk;

    public static void main(String[] args) throws Exception {
//      连接zookeeper服务端
        zk =new ZkClient("localhost:2181",10000,5000,new BytesPushThroughSerializer());
//      从库里面取出已经设定好的数据
        url = zk.readData("/db/url");
        driverClass = zk.readData("/db/driverClass");
        userName = zk.readData("/db/userName");
        password = zk.readData("/db/password");

//      开启一个监控功能
        zk.subscribeDataChanges("/db/url", new IZkDataListener() {
            /**
             * 监控删除
             * @param path
             */
            public void handleDataDeleted(String path){
                System.out.println("监控删除");
            }

            /**
             * 监控修改
             * @param path
             * @param data
             * @throws Exception
             */
            public void handleDataChange(String path, Object data) throws Exception {
                url = zk.readData("/db/url");
                connction = getConnction(new String(url),new String(driverClass),new String(userName),new String(password));
                List();
                System.out.println("=============================");
            }
        });
//      因为要测试监控功能,这个来了一个四循环,不让这个进程结束
        while (true) {
            Thread.sleep(Integer.MAX_VALUE);
        }
    }

//  封装一个连接数据库的Connection
    public static Connection getConnction(String url, String driverClass, String userName, String password) throws Exception{
        Class.forName(driverClass);
        connction = DriverManager.getConnection(url,userName,password);
        return connction;
    }

//  封装一个简单的查询方法
    public static void List() throws Exception{
        String sql ="select * from userinfo";
        PreparedStatement ps=connction.prepareStatement(sql);

        ResultSet rSet =ps.executeQuery();  //执行sql语句
        ResultSetMetaData metaData = rSet.getMetaData();  //new一个getMetaData
        int columnCount = metaData.getColumnCount();  //获取表中的总列数

        for (int i = 1; i <= columnCount; i++) {
            System.out.print(metaData.getColumnLabel(i)+"\t");  //获取列名
        }
        System.out.println();
        while (rSet.next()) {
            for (int i = 1; i <=columnCount ; i++) {
                System.out.print(rSet.getString(i)+"\t");
            }
            System.out.println();
        }
    }
}

在这里我用的是mysql数据库,两个库里面分别创建了一个用户表,一张有六条数据,一张只有一条数据,为了演示zookeeper的监控功能,我就去修改存在zookeeper里面的url数据:

set /db/url jdbc:mysql://localhost:3306/test
set /db/url jdbc:mysql://localhost:3306/demo

运行结果如下:

因为上面代码有配置了监控db/url这个path,只要我修改db/url这个属性,zookeeper就会自动监控出来,显示相应的数据。。。。。。。。。。。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值